LINQKit icon indicating copy to clipboard operation
LINQKit copied to clipboard

Entity Framework Core 5 - and LinqKit.Microsoft.EntityFrameworkCore 5.0.x not working with expressions in subqueries

Open rizi opened this issue 3 years ago • 3 comments

I've created a very sample solution to reproduce the issue:

I only use the LinqKit.Microsoft.EntityFrameworkCore 5.0.x package, do I need something more? The code below was working fine in EF 6 with the corresponding NuGet package, and as far as I understand when reading the readme of this repo, it should still work with EF Core 5.x, am I right?

I also tried to call .Expand() on the expression created by the FilterNames(...), but the same error occurs. I also tried to use a expression instead of the func (name => student.Name.Contains(name)) and than call .Compile() on the expression, but the same error occurs.

I got this exception: System.InvalidOperationException: 'The LINQ expression 'DbSet<Student>() .Where(s => __names_0 .Any(name => s.Name.Contains(name)))' 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 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.'

private static async Task Main(string[] args)
        {
            Console.WriteLine("EF Core Sample...");

            IUnityContainer container = InitUnityContainer();

           //the context is resolved by unity (ioc container)
            SchoolContext schoolContext = container.Resolve<SchoolContext>();

            Expression<Func<Student, bool>> filterNames = FilterNames(new List<string> { "MIH" });

            IReadOnlyCollection<Student> students =
                await schoolContext.Students
                    .AsExpandableEFCore()
                    .Where(filterNames)
                    .ToListAsync();
        }

        private static Expression<Func<Student, bool>> FilterNames(IReadOnlyCollection<string> names)
        {
            ExpressionStarter<Student> filterExpression = PredicateBuilder.New<Student>(true);

            if (!names.Any())
                return filterExpression;
            
            return filterExpression.And(student => names.Any(name => student.Name.Contains(name)));
        }

rizi avatar Sep 28 '21 06:09 rizi

This is EF Core limitation. With local collections it can do only Contains or VERY simple Any, which is not your case. Check my SO answer

sdanyliv avatar Nov 29 '21 20:11 sdanyliv

This is EF Core limitation. With local collections it can do only Contains or VERY simple Any, which is not your case. Check my SO answer

Thx for the answer, I solved it quite similar, but I hoped there is a way to make it work. Do you know any details about the EF Core limitation? If so I would open an issue in the EF core repo.

Br

rizi avatar Nov 29 '21 20:11 rizi

You are not alone: https://github.com/dotnet/efcore/issues/19070

sdanyliv avatar Nov 29 '21 22:11 sdanyliv