question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Type-Generic Where Clause unable to be translated when using projections (EF Core 3.1.1)

See original GitHub issue

When 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:closed
  • Created 4 years ago
  • Comments:12 (7 by maintainers)

github_iconTop GitHub Comments

1reaction
smitpatelcommented, Feb 10, 2020

Duplicate of #19087

1reaction
NetTecturecommented, Feb 8, 2020

@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.

Read more comments on GitHub >

github_iconTop 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 >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found