dbContext.MyEntity.Where(x => x.This == That).ForSystemTime(historicDateTime).OrderBy(o => o.Something);
SELECT ... FROM MyEntity FOR SYSTEM_TIME AS OF historicDateTime WHERE ... ORDER BY ...
public static IQueryable<T> ForSystemTime<T>(this IQueryable<T> source, DateTimeOffset systemTime) { ... }
class ForSystemTimeResultOperator : SequenceTypePreservingResultOperatorBase { ... }
public class ForSystemTimeExpressionNode : ResultOperatorExpressionNodeBase { ... }
public static MyDbContext GetDbContext()
{
var services = new ServiceCollection();
services.AddEntityFrameworkSqlServer();
services.AddScoped<IQueryParser, MyCustomizedQueryParser>();
var provider = services.BuildServiceProvider();
var config = new DbContextOptionsBuilder<MyDbContext>();
config.UseInternalServiceProvider(provider);
config.UseSqlServer(connection);
var db = new MyDbContext(config.Options);
return db;
}
System.NotImplementedException
HResult=0x80004001
Message=TemporalQuery.ForSystemTimeResultOperator
Source=Microsoft.EntityFrameworkCore
StackTrace:
at Microsoft.EntityFrameworkCore.Query.ResultOperatorHandler.HandleResultOperator(EntityQueryModelVisitor entityQueryModelVisitor, ResultOperatorBase resultOperator, QueryModel queryModel)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalResultOperatorHandler.HandlerContext.EvalOnClient(Boolean requiresClientResultOperator)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalResultOperatorHandler.HandleResultOperator(EntityQueryModelVisitor entityQueryModelVisitor, ResultOperatorBase resultOperator, QueryModel queryModel)
at Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.VisitResultOperator(ResultOperatorBase resultOperator, QueryModel queryModel, Int32 index)
at Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.VisitResultOperator(ResultOperatorBase resultOperator, QueryModel queryModel, Int32 index)
at Remotion.Linq.QueryModelVisitorBase.VisitResultOperators(ObservableCollection´1 resultOperators, QueryModel queryModel)
at Remotion.Linq.QueryModelVisitorBase.VisitQueryModel(QueryModel queryModel)
at Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.VisitQueryModel(QueryModel queryModel)
at Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.VisitQueryModel(QueryModel queryModel)
at Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.CreateQueryExecutor[TResult](QueryModel queryModel)
at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](QueryModel queryModel)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](Expression query, INodeTypeProvider nodeTypeProvider, IDatabase database, IDiagnosticsLogger´1 logger, Type contextType)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass15_0´1.<Execute>b__0()
at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore[TFunc](Object cacheKey, Func´1 compiler)
at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func´1 compiler)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)
at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression)
at Remotion.Linq.QueryableBase´1.GetEnumerator()
at TemporalQuery.Program.QueryAgreements() in C:\Users\mio\source\repos\TemporalQuery\TemporalQuery\Program.cs:line 26
at TemporalQuery.Program.Main(String[] args) in C:\Users\mio\source\repos\TemporalQuery\TemporalQuery\Program.cs:line 11
4. Add code handling the result operator to your LINQ provider back-end
Now, this is simple again. Using the registered expression node parser, re-linq now detects the extension methods and creates a result operator for it. You can inspect a QueryModel’s result operators via the ResultOperators collection. If you have a QueryModelVisitor, just override the VisitResultOperator method and check the result operator’s type.
var services = new ServiceCollection();
services.AddEntityFrameworkSqlServer();
services.AddSingleton<INodeTypeProviderFactory, MethodInfoBasedNodeTypeRegistryFactoryForTemporalQueries>();
//services.AddScoped<IQueryModelVisitor, EntityQueryModelVisitorForTemporalQueries>();
//services.AddScoped<QueryModelVisitorBase, EntityQueryModelVisitorForTemporalQueries>();
//services.AddScoped<EntityQueryModelVisitor, EFEntityQueryModelVisitorForTemporalQueries>();
//services.AddSingleton<EntityQueryModelVisitorFactory, EFEntityQueryModelVisitorForTemporalQueries>();
var provider = services.BuildServiceProvider();
services.AddScoped<IResultOperatorHandler, ResultOperatorHandlerForTemporalQueries>();