You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In previous versions of EF one could use a HashSet in the query with Contains. With EFCore 3.0 it doesn't work anymore
Steps to reproduce
public class TestContext : DbContext
{
public DbSet<Item> Items { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
options.UseSqlServer("Data Source=.\\SQLEXPRESS;Initial Catalog=TestDB;Integrated Security=True");
}
}
public class Item
{
public int ItemId { get; set; }
}
class Program
{
public static async Task Main()
{
using var context = new TestContext();
HashSet<int> ids = new HashSet<int> { 1 }; //doesn't work
//IEnumerable<int> ids = new HashSet<int> { 1 }; //works
List<Item> items = await (from item in context.Items
where ids.Contains(item.ItemId)
select item).ToListAsync();
}
}
When the static type of the variable is IEnumerable the LINQ extension method is used and the method works as expected. When the static type is HashSet EF doesn't recognize the HashSet.Contains instance method and I get an exception. Note that this same code works fine with EF Code 2.2. I believe this case should be supported because 1) it is a regression, 2) it is annoying to have to change the static type of the variable to make EF happy, 3) the issue is only reported at runtime and with an error message that incorrectly points to client evaluation, 4) the pattern is fairly common - gather a bunch of ids that should be included or excluded from the result but do so in set because the way you collect them includes duplicates
System.InvalidOperationException
HResult=0x80131509
Message=The LINQ expression 'Where(
source: DbSet,
predicate: (i) => (Unhandled parameter: __ids_0).Contains(i.ItemId))' 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.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 System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
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_01.<ExecuteAsync>b__0() at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore[TFunc](Object cacheKey, Func1 compiler)
at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func1 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.EntityQueryable1.GetAsyncEnumerator(CancellationToken cancellationToken)
at System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable1.GetAsyncEnumerator() at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.<ToListAsync>d__641.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 EFCoreBugs.Program.
In previous versions of EF one could use a HashSet in the query with Contains. With EFCore 3.0 it doesn't work anymore
Steps to reproduce
When the static type of the variable is IEnumerable the LINQ extension method is used and the method works as expected. When the static type is HashSet EF doesn't recognize the HashSet.Contains instance method and I get an exception. Note that this same code works fine with EF Code 2.2. I believe this case should be supported because 1) it is a regression, 2) it is annoying to have to change the static type of the variable to make EF happy, 3) the issue is only reported at runtime and with an error message that incorrectly points to client evaluation, 4) the pattern is fairly common - gather a bunch of ids that should be included or excluded from the result but do so in set because the way you collect them includes duplicates
Further technical details
EF Core version: 3.0
Database provider: Microsoft.EntityFrameworkCore.SqlServer (maybe others)
Target framework: .NET Core 3.0
The text was updated successfully, but these errors were encountered: