Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exception is thrown when materializing query with IQueryable<T>.AsOf(DateTime) #6

Closed
dart13 opened this issue Sep 25, 2020 · 2 comments

Comments

@dart13
Copy link

dart13 commented Sep 25, 2020

I have the following issue:

this linq query

var result = _context.DistributionListEntries .AsOf(pager.TimeIndex) .Where(x => x.DistributionListId == distributionListId) .Include(x => x.PlaceholderValues) .Skip((pager.PageNumber - 1) * pager.PageSize).Take(pager.PageSize) .AsNoTracking();

when materialized

return await result.ToListAsync();

throws this exception

Message:
System.NotImplementedException : Unhandled method: AsOf
Stack Trace: QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression) RelationalQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression) MethodCallExpression.Accept(ExpressionVisitor visitor) ExpressionVisitor.Visit(Expression node) QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression) RelationalQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression) MethodCallExpression.Accept(ExpressionVisitor visitor) ExpressionVisitor.Visit(Expression node) QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression) RelationalQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression) MethodCallExpression.Accept(ExpressionVisitor visitor) ExpressionVisitor.Visit(Expression node) QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression) RelationalQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression) MethodCallExpression.Accept(ExpressionVisitor visitor) ExpressionVisitor.Visit(Expression node) QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression) RelationalQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression) MethodCallExpression.Accept(ExpressionVisitor visitor) ExpressionVisitor.Visit(Expression node) QueryCompilationContext.CreateQueryExecutor[TResult](Expression query) Database.CompileQuery[TResult](Expression query, Boolean async) QueryCompiler.CompileQueryCore[TResult](IDatabase database, Expression query, IModel model, Boolean async) <>c__DisplayClass12_0'1.<ExecuteAsync>b__0() CompiledQueryCache.GetOrAddQueryCore[TFunc](Object cacheKey, Func'1 compiler) CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func'1 compiler) QueryCompiler.ExecuteAsync[TResult](Expression query, CancellationToken cancellationToken) EntityQueryProvider.ExecuteAsync[TResult](Expression expression, CancellationToken cancellationToken) EntityQueryable'1.GetAsyncEnumerator(CancellationToken cancellationToken) ConfiguredCancelableAsyncEnumerable'1.GetAsyncEnumerator() EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable'1 source, CancellationToken cancellationToken) DLPOCRepository.GetTemporalEntriesForDistributionList(Int64 distributionListId, TemporalPagingFilter pager) line 142 DLPOCRepositoryTest.TestDLRepositoryPaging() line 51 --- End of stack trace from previous location where exception was thrown ---

Entities

DistributionListEntry

and

PlaceholderValue

are marked as temporal
builder.Entity<DistributionListEntry>(dle => dle.HasTemporalTable()); builder.Entity<EntryPlaceholderValue>(epv => epv.HasTemporalTable());

and DbContext is initialized

 `services.AddDbContext<DLPOCContext>(
            opt => opt
                .UseSqlServer(Configuration.GetConnectionString("DLPOC"))
                .EnableTemporalTableQueries());`

Did I miss some configuration options?

Is there are sample project which implements 'efcore-temporal-query'?

@Adam-Langley
Copy link
Owner

Adam-Langley commented Sep 26, 2020

Hi @dart13,
I can see in your stack trace that your RelationalQueryableMethodTranslatingExpressionVisitor is the default built-in one - not the AsOf implementation (AsOfQueryableMethodTranslatingExpressionVisitor).
The default implementation has no idea how to translate the AsOf method call - hence your error.

That particular expression visitor is replaced by the EnableTemporalTableQueries extension method that you have used (correctly) above.

Take a look in the source - there is a test which will skip over the registration if you are not utilising the internal service provider.

// If service provision is NOT being performed internally, we cannot replace services.
var coreOptions = optionsBuilder.Options.GetExtension<CoreOptionsExtension>();
if (coreOptions.InternalServiceProvider == null)
{
return optionsBuilder
// replace the service responsible for generating SQL strings
.ReplaceService<IQuerySqlGeneratorFactory, AsOfQuerySqlGeneratorFactory>()
// replace the service responsible for traversing the Linq AST (a.k.a Query Methods)
.ReplaceService<IQueryableMethodTranslatingExpressionVisitorFactory, AsOfQueryableMethodTranslatingExpressionVisitorFactory>()
// replace the service responsible for providing instances of SqlExpressions
.ReplaceService<ISqlExpressionFactory, AsOfSqlExpressionFactory>();
}
else
return optionsBuilder;

Try this test yourself at runtime, and see if this is your problem.

If you are using external service provisioning, you will not be able to use this library as-is. You will need to write your own 'EnableTemporalTableQueries' method (which is possible) - but you just need to manually register all the Ef Core services.

@dart13
Copy link
Author

dart13 commented Oct 14, 2020

Hi @Adam-Langley ,

thank you for your prompt reply.
Bad initialization of dbcontext in unit test was the cause of the error. Hopefully, this complete answer you provided will help others as well.

I am hoping that MS will provide better support for temporal tables in EF core soon, until then I'll use this great plug-in you have created.

best regards
Darko

@dart13 dart13 closed this as completed Oct 14, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants