Type-Generic Where Clause unable to be translated when using projections (EF Core 3.1.1)
See original GitHub issueWhen trying to access a defined property on a generic, projected type, the object in the Where
clause lambda is unable to be translated.
public virtual async Task<IEnumerable<T>> GetAsync(IEnumerable<Guid> ids)
=> await this.repository.Read().Where(r => r.Id.ToString().Contains("0")).ToListAsync();
Outputs:
System.InvalidOperationException
HResult=0x80131509
Message=The LINQ expression 'DbSet<Person>
.Where(p => new Person{
ContactNumber = p.ContactNumber,
Email = p.Email,
FullName = p.FullName,
Id = p.Id
}
.Id.ToString().Contains("0"))' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync(). See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
Source=Microsoft.EntityFrameworkCore
Steps to reproduce
//service class, either method fails
public abstract class Service<T> : IService<T> where T : class, ICommonModel {
protected readonly IRepository<T> repository;
public Service(IRepository<T> repository)
=> this.repository = repository;
public virtual async Task<IEnumerable<T>> GetAsync(IEnumerable<Guid> ids)
=> await this.repository.Read().Where(r => ids.Contains(r.Id)).ToListAsync();
public virtual async Task<IDictionary<Guid, T>> GetDictionaryAsync(IEnumerable<Guid> ids)
=> await this.repository.Read().Where(r => r.Id.ToString().Contains("0")).ToDictionaryAsync(i => i.Id, i => i);
}
}
//repo class
public abstract class Repository<TCommon, TData> : IRepository<TCommon>
where TCommon : class, ICommonModel
where TData : class, IDataModel {
protected AppContext Context { get; }
protected IMapper Mapper { get; }
public Repository(AppContext context, IMapper mapper) {
this.Context = context;
this.Mapper = mapper;
}
public virtual IQueryable<TCommon> Read()
=> this.Context.Set<TData>().ProjectTo<TCommon>(this.Mapper.ConfigurationProvider);
}
}
//interfaces
public interface ICommonModel {
Guid Id { get; set; }
}
public interface IDataModel {
Guid Id { get; set; }
}
}
Stack Trace:
System.InvalidOperationException
HResult=0x80131509
Message=The LINQ expression 'DbSet<Person>
.Where(p => new Person{
ContactNumber = p.ContactNumber,
Email = p.Email,
FullName = p.FullName,
Id = p.Id
}
.Id.ToString().Contains("0"))' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync(). See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
Source=Microsoft.EntityFrameworkCore
StackTrace:
at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.<VisitMethodCall>g__CheckTranslated|8_0(ShapedQueryExpression translated, <>c__DisplayClass8_0& )
at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor[TResult](Expression query)
at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](Expression query, Boolean async)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](IDatabase database, Expression query, IModel model, Boolean async)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass12_0`1.<ExecuteAsync>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.ExecuteAsync[TResult](Expression query, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAsync[TResult](Expression expression, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.GetAsyncEnumerator(CancellationToken cancellationToken)
at System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable`1.GetAsyncEnumerator()
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.<ToDictionaryAsync>d__90`3.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at Denali.Services.Service`1.<GetDictionaryAsync>d__9.MoveNext() in C:\Users\tleahy\source\repos\Denali.API\Services\Service.cs:line 42
This exception was originally thrown at this call stack:
Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall.__CheckTranslated|8_0(Microsoft.EntityFrameworkCore.Query.ShapedQueryExpression, ref Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.<>c__DisplayClass8_0)
Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(System.Linq.Expressions.MethodCallExpression)
Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(System.Linq.Expressions.MethodCallExpression)
System.Linq.Expressions.MethodCallExpression.Accept(System.Linq.Expressions.ExpressionVisitor)
Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(System.Linq.Expressions.MethodCallExpression)
Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(System.Linq.Expressions.MethodCallExpression)
System.Linq.Expressions.MethodCallExpression.Accept(System.Linq.Expressions.ExpressionVisitor)
...
[Call Stack Truncated]
Further technical details
EF Core version: 3.1.1 Database provider: Microsoft.EntityFrameworkCore.SqlServer Target framework: .NET Core 3.1 Operating system: Windows IDE: Visual Studio 2019 16.4.3
Issue Analytics
- State:
- Created 4 years ago
- Comments:12 (7 by maintainers)
Top Results From Across the Web
Basic Type-Generic EF Core 3.1 -> SQL Server Where ...
I have a basic generic LINQ query that takes an argument of type T where T :class, ICommonModel , this translates via a...
Read more >Client vs. Server Evaluation - EF Core
If EF Core detects an expression, in any place other than the top-level projection, which can't be translated to the server, then it...
Read more >New features in Entity Framework Core 3.x - EF Core
x detects expressions that can't be translated anywhere else in the query, it throws a runtime exception. To evaluate a predicate condition on ......
Read more >EF Projections on computed properties and methods without a ...
At this stage, EF is fully equipped to translate any query that queries on a property or method that is marked with [Projectable]...
Read more >After 10+ years of EF/EF Core, I can no longer justify using it.
I've been using EF for over a decade, and it just feels completely wrong every time I do. The time you save typing...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Duplicate of #19087
@tj111
I have to disagree with you here. There is hope. Hope in the name of 5.0. As someone from the financial markets let me tell you why there is hope. HOPE DIES LAST. When you have moved off to a better product and EfCore is not fixed in 10 years, there STILL is hope left.
And this is the ONLY reason why there is still hope.
Btw., in another thread - https://github.com/dotnet/efcore/issues/19830 - @ajcvickers said:
“I talk to many developers using EF Core, both posting on here, and big customers running serious apps in major companies (which are sometimes the same).”
I find that extremely hard to believe given that it does pretty much not matter what I try, if it is not on the level of Hello World, it blows.