PredicateBuilder is not working on EF Core
Asked Answered
D

1

6
public string[] FindAssets2()
{
    string[] result;

    using (var ctx = new StockContext())
    {
        var predicate = PredicateBuilder.New<Asset>().Or(asset => asset.Symbol.Contains("TSLA"));

        result = ctx.Assets.AsExpandable()
        .Where(predicate)
        .Select(z => z.Symbol)
        .ToArray();
    }

    return result;
}

Just a piece of simple codes. It throws me

Exception: Unhandled expression type: 'Extension'
LinqKit.ExpressionVisitor.Visit(Expression exp)
LinqKit.ExpressionVisitor.VisitExpressionList(ReadOnlyCollection<Expression> original)
LinqKit.ExpressionVisitor.VisitMethodCall(MethodCallExpression m)
LinqKit.ExpressionVisitor.Visit(Expression exp)
LinqKit.Extensions.Expand(Expression expr)
LinqKit.ExpandableQueryProvider<T>.System.Linq.IQueryProvider.CreateQuery<TElement>(Expression expression)
System.Linq.Queryable.Where<TSource>(IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate)

Below is my installed package

    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.0-preview.4.20220.10" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.0-preview.4.20220.10" />
    <PackageReference Include="LINQKit.Core" Version="1.1.17" />

Any help would be appreciate. Many thanks!

Durand answered 25/6, 2020 at 15:6 Comment(4)
What type does predicate say it is when you hover over it in Visual Studio?Cryoscopy
and also if you just ToString() it - what does it look like?Misapprehend
ultimately, though, it looks whatever this is: is probably something to report to whoever wrote LinqKitMisapprehend
FOR ALL LATE VISITOR AND WHO WANT TO USE EFC WITH LINQKIT, PLEASE CONSIDER TO USE EFC 5.0.0-preview.2.20120.8 ON https://www.nuget.org/packages/Microsoft.EntityFrameworkCore/5.0.0-preview.2.20120.8. THIS IS THE ONLY VERSION WHICH WORK WITH LINQKIT AT THE MOMENT.Durand
T
5

It seems that EF-core 5 doesn't play nice with AsExpandable. Or rather the other way around. It worked with EF3, but apparently Linqkit isn't resilient to library-specific idiosyncrasies of expression trees.

There is a work-around for this case. As expained here, predicate is not an Expression, but an ExpressionStarter, which implicitly converts to Expression<Func<T, bool>> and Func<T, bool>. Therefore, queries with predicates on top-level entities (say: EF's IQueryables) work without AsExpandable:

result = ctx.Assets   // No '.AsExpandable()'
    .Where(predicate) // Implicit conversion of 'predicate' to Expression<Func<Asset,boo>l>
    .Select(z => z.Symbol)
    .ToArray();

The bad news is that without any fixes in this area, you won't be able to use AsExpandable when it's really necessary, for example for predicates on collection navigation properties.

Threephase answered 25/6, 2020 at 19:57 Comment(4)
Gertt, the exception call stack contains LinqKit only methods, so isn't it the other way around - LinqKit doesn't play well with EFC (and any other code which emits custom (a.k.a. "extension") expressions) in the query expression tree?Warms
@Ivan It's the combination of Linqkit and EF5. The same Linqkit version works with EF3. I don't know who's to blame. Of course, in a sense, it's Linqkit. EF5 works (sort of), add Linqkit to it and it breaks.Threephase
Apparently EFC5 uses custom expressions. Expression visitors should skip such expressions. LinqKit is outdated, the problem is there and should (if) fixed there and not in EFC.Warms
@Ivan That I agree with. It's not the world's responsibility to please Linqkit.Threephase

© 2022 - 2024 — McMap. All rights reserved.