@@ -560,6 +560,13 @@ public virtual MappingSchema GetMappingSchema(
560560
561561		static   readonly  MethodInfo  ToSql  =  MemberHelper . MethodOfGeneric ( ( )  =>  Sql . ToSql ( 1 ) ) ; 
562562
563+ 		private  static   readonly  MethodInfo  AsSqlServerTable     =  MemberHelper . MethodOfGeneric < ITable < object > > ( q =>  DataProvider . SqlServer . SqlServerTools . AsSqlServer ( q ) ) ; 
564+ 		private  static   readonly  MethodInfo  TemporalAsOfTable    =  MemberHelper . MethodOfGeneric < ISqlServerSpecificTable < object > > ( t =>  SqlServerHints . TemporalTableAsOf ( t ,  default ) ) ; 
565+ 		private  static   readonly  MethodInfo  TemporalFromTo       =  MemberHelper . MethodOfGeneric < ISqlServerSpecificTable < object > > ( t =>  SqlServerHints . TemporalTableFromTo ( t ,  default ,  default ) ) ; 
566+ 		private  static   readonly  MethodInfo  TemporalBetween      =  MemberHelper . MethodOfGeneric < ISqlServerSpecificTable < object > > ( t =>  SqlServerHints . TemporalTableBetween ( t ,  default ,  default ) ) ; 
567+ 		private  static   readonly  MethodInfo  TemporalContainedIn  =  MemberHelper . MethodOfGeneric < ISqlServerSpecificTable < object > > ( t =>  SqlServerHints . TemporalTableContainedIn ( t ,  default ,  default ) ) ; 
568+ 		private  static   readonly  MethodInfo  TemporalAll          =  MemberHelper . MethodOfGeneric < ISqlServerSpecificTable < object > > ( t =>  SqlServerHints . TemporalTableAll ( t ) ) ; 
569+ 
563570		/// <summary> 
564571		/// Removes conversions from expression. 
565572		/// </summary> 
@@ -726,6 +733,27 @@ static List<Expression> CompactTree(List<Expression> items, ExpressionType nodeT
726733			return  result ; 
727734		} 
728735
736+ 		/// <summary> 
737+ 		/// Gets current property value via reflection. 
738+ 		/// </summary> 
739+ 		/// <typeparam name="TValue">Property value type.</typeparam> 
740+ 		/// <param name="obj">Object instance</param> 
741+ 		/// <param name="propName">Property name</param> 
742+ 		/// <returns>Property value.</returns> 
743+ 		/// <exception cref="InvalidOperationException"></exception> 
744+ 		protected  static   TValue  GetPropValue < TValue > ( object  obj ,  string  propName ) 
745+ 		{ 
746+ 			var  prop  =  obj . GetType ( ) . GetProperty ( propName ) ; 
747+ 			if  ( prop  ==  null ) 
748+ 			{ 
749+ 				throw  new  InvalidOperationException ( $ "Property { obj . GetType ( ) . Name } .{ propName }  not found.") ; 
750+ 			} 
751+ 			var  propValue  =  prop . GetValue ( obj ) ; 
752+ 			if  ( propValue  ==  default ) 
753+ 				return  default ! ; 
754+ 			return  ( TValue ) propValue ; 
755+ 		} 
756+ 
729757		/// <summary> 
730758		/// Transforms EF Core expression tree to LINQ To DB expression. 
731759		/// Method replaces EF Core <see cref="EntityQueryable{TResult}"/> instances with LINQ To DB 
@@ -948,19 +976,12 @@ TransformInfo LocalTransform(Expression e)
948976
949977					case  ExpressionType . Extension : 
950978					{ 
951- 						if  ( dc  !=  null  &&  e  is  FromSqlQueryRootExpression  fromSqlQueryRoot ) 
952- 						{ 
953- 							//convert the arguments from the FromSqlOnQueryable method from EF, to a L2DB FromSql call 
954- 							return  new  TransformInfo ( Expression . Call ( null , 
955- 								L2DBFromSqlMethodInfo . MakeGenericMethod ( fromSqlQueryRoot . EntityType . ClrType ) , 
956- 								Expression . Constant ( dc ) , 
957- 								Expression . New ( RawSqlStringConstructor ,  Expression . Constant ( fromSqlQueryRoot . Sql ) ) , 
958- 								fromSqlQueryRoot . Argument ) ) ; 
959- 						} 
960- 						else  if  ( dc  !=  null  &&  e  is  EntityQueryRootExpression  queryRoot ) 
979+ 						if  ( dc  !=  null ) 
961980						{ 
962- 							var  newExpr  =  Expression . Call ( null ,  Methods . LinqToDB . GetTable . MakeGenericMethod ( queryRoot . EntityType . ClrType ) ,  Expression . Constant ( dc ) ) ; 
963- 							return  new  TransformInfo ( newExpr ) ; 
981+ 							if  ( e  is  QueryRootExpression  queryRoot ) 
982+ 							{ 
983+ 								return  new  TransformInfo ( TransformQueryRootExpression ( dc ,  queryRoot ) ) ; 
984+ 							} 
964985						} 
965986
966987						break ; 
@@ -982,6 +1003,97 @@ TransformInfo LocalTransform(Expression e)
9821003			return  newExpression ; 
9831004		} 
9841005
1006+ 		/// <summary> 
1007+ 		/// Transforms <see cref="QueryRootExpression"/> descendants to linq2db analogue. Handles Temporal tables also. 
1008+ 		/// </summary> 
1009+ 		/// <param name="dc">Data context.</param> 
1010+ 		/// <param name="queryRoot">Query root expression</param> 
1011+ 		/// <returns>Transformed expression.</returns> 
1012+ 		protected  virtual  Expression  TransformQueryRootExpression ( IDataContext  dc ,  QueryRootExpression  queryRoot ) 
1013+ 		{ 
1014+ 			static   Expression  GetAsOfSqlServer ( Expression  getTableExpr ,  Type  entityType ) 
1015+ 			{ 
1016+ 				return  Expression . Call ( 
1017+ 					AsSqlServerTable . MakeGenericMethod ( entityType ) , 
1018+ 					getTableExpr ) ; 
1019+ 			} 
1020+ 
1021+ 			if  ( queryRoot  is  FromSqlQueryRootExpression  fromSqlQueryRoot ) 
1022+ 			{ 
1023+ 				//convert the arguments from the FromSqlOnQueryable method from EF, to a L2DB FromSql call 
1024+ 				return  Expression . Call ( null , 
1025+ 					L2DBFromSqlMethodInfo . MakeGenericMethod ( fromSqlQueryRoot . EntityType . ClrType ) , 
1026+ 					Expression . Constant ( dc ) , 
1027+ 					Expression . New ( RawSqlStringConstructor ,  Expression . Constant ( fromSqlQueryRoot . Sql ) ) , 
1028+ 					fromSqlQueryRoot . Argument ) ; 
1029+ 			} 
1030+ 
1031+ 			var  entityType  =  queryRoot . ElementType ; 
1032+ 			var  getTableExpr  =  Expression . Call ( null ,  Methods . LinqToDB . GetTable . MakeGenericMethod ( entityType ) , 
1033+ 				Expression . Constant ( dc ) ) ; 
1034+ 
1035+ 			var  expressionTypeName  =  queryRoot . GetType ( ) . Name ; 
1036+ 			if  ( expressionTypeName  ==  "TemporalAsOfQueryRootExpression" ) 
1037+ 			{ 
1038+ 				var  pointInTime  =  GetPropValue < DateTime > ( queryRoot ,  "PointInTime" ) ; 
1039+ 
1040+ 				var  asOf  =  Expression . Call ( TemporalAsOfTable . MakeGenericMethod ( entityType ) ,  
1041+ 					GetAsOfSqlServer ( getTableExpr ,  entityType ) , 
1042+ 					Expression . Constant ( pointInTime ) ) ; 
1043+ 
1044+ 				return  asOf ; 
1045+ 			} 
1046+ 
1047+ 			if  ( expressionTypeName  ==  "TemporalFromToQueryRootExpression" ) 
1048+ 			{ 
1049+ 				var  from   =  GetPropValue < DateTime > ( queryRoot ,  "From" ) ; 
1050+ 				var  to  =  GetPropValue < DateTime > ( queryRoot ,  "To" ) ; 
1051+ 
1052+ 				var  fromTo  =  Expression . Call ( TemporalFromTo . MakeGenericMethod ( entityType ) , 
1053+ 					GetAsOfSqlServer ( getTableExpr ,  entityType ) , 
1054+ 					Expression . Constant ( from ) , 
1055+ 					Expression . Constant ( to ) ) ; 
1056+ 
1057+ 				return  fromTo ; 
1058+ 			} 
1059+ 
1060+ 			if  ( expressionTypeName  ==  "TemporalBetweenQueryRootExpression" ) 
1061+ 			{ 
1062+ 				var  from   =  GetPropValue < DateTime > ( queryRoot ,  "From" ) ; 
1063+ 				var  to  =  GetPropValue < DateTime > ( queryRoot ,  "To" ) ; 
1064+ 
1065+ 				var  fromTo  =  Expression . Call ( TemporalBetween . MakeGenericMethod ( entityType ) , 
1066+ 					GetAsOfSqlServer ( getTableExpr ,  entityType ) , 
1067+ 					Expression . Constant ( from ) , 
1068+ 					Expression . Constant ( to ) ) ; 
1069+ 
1070+ 				return  fromTo ; 
1071+ 			} 
1072+ 
1073+ 			if  ( expressionTypeName  ==  "TemporalContainedInQueryRootExpression" ) 
1074+ 			{ 
1075+ 				var  from   =  GetPropValue < DateTime > ( queryRoot ,  "From" ) ; 
1076+ 				var  to  =  GetPropValue < DateTime > ( queryRoot ,  "To" ) ; 
1077+ 
1078+ 				var  fromTo  =  Expression . Call ( TemporalContainedIn . MakeGenericMethod ( entityType ) , 
1079+ 					GetAsOfSqlServer ( getTableExpr ,  entityType ) , 
1080+ 					Expression . Constant ( from ) , 
1081+ 					Expression . Constant ( to ) ) ; 
1082+ 
1083+ 				return  fromTo ; 
1084+ 			} 
1085+ 
1086+ 			if  ( expressionTypeName  ==  "TemporalAllQueryRootExpression" ) 
1087+ 			{ 
1088+ 				var  all  =  Expression . Call ( TemporalAll . MakeGenericMethod ( entityType ) , 
1089+ 					GetAsOfSqlServer ( getTableExpr ,  entityType ) ) ; 
1090+ 
1091+ 				return  all ; 
1092+ 			} 
1093+ 
1094+ 			return  getTableExpr ; 
1095+ 		} 
1096+ 
9851097		static   Expression  EnsureEnumerable ( Expression  expression ,  MappingSchema  mappingSchema ) 
9861098		{ 
9871099			var  enumerable  =  typeof ( IEnumerable < > ) . MakeGenericType ( GetEnumerableElementType ( expression . Type ,  mappingSchema ) ) ; 
0 commit comments