Use LinqKit PredicateBuilder for a related model (EF Core)

I want to use the LinqKit PredicateBuilder and pass the predicate to the method .Anyfor the associated model.

So I want to build a predicate:

var castCondition = PredicateBuilder.New<CastInfo>(true);

if (movies != null && movies.Length > 0)
{
    castCondition = castCondition.And(c => movies.Contains(c.MovieId));
}
if (roleType > 0)
{
    castCondition = castCondition.And(c => c.RoleId == roleType);
}

And then use it to filter the model that is related to the model in the predicate:

IQueryable<Name> result = _context.Name.AsExpandable().Where(n => n.CastInfo.Any(castCondition));
return await result.OrderBy(n => n.Name1).Take(25).ToListAsync();

But it causes System.NotSupportedException: Could not parse expression 'n.CastInfo.Any(Convert(__castCondition_0, Func``2))': The given arguments did not match the expected arguments: Object of type 'System.Linq.Expressions.UnaryExpression' cannot be converted to type 'System.Linq.Expressions.LambdaExpression'.

I saw a similar question and the answer there suggests using .Compile. Or another question that creates an additional predicate.

So, I tried to use an additional predicate

var tp = PredicateBuilder.New<Name>(true);
tp = tp.And(n => n.CastInfo.Any(castCondition.Compile()));
IQueryable<Name> result = _context.Name.AsExpandable().Where(tp);

Or use compilation directly

IQueryable<Name> result = _context.Name.AsExpandable().Where(n => n.CastInfo.Any(castCondition.Compile()));

But I have a compilation error: System.NotSupportedException: Could not parse expression 'n.CastInfo.Any(__Compile_0)'

So, is it possible to convert the result from PredicateBuilder to go to Any?

. , , , .

System.Linq.Expressions.Expression<Func<CastInfo,bool>> castExpression = (c => true);
if (movies != null && movies.Length > 0)
{
    castExpression = (c => movies.Contains(c.MovieId));
}
if (roleType > 0)
{
    var existingExpression = castExpression;
    castExpression = c => existingExpression.Invoke(c) && c.RoleId == roleType;
}
IQueryable<Name> result = _context.Name.AsExpandable().Where(n => n.CastInfo.Any(castExpression.Compile()));
return await result.OrderBy(n => n.Name1).Take(25).ToListAsync();

, - .

: dotnet core 2.0 LinqKit.Microsoft.EntityFrameworkCore 1.1.10

+4
1

, , castCondition Expression<Func<CastInfo, bool>> ( PredicateBuilder).

, n.CastInfo.Any(castCondition) (, CastInfo - , Enumerable.Any, Func<CastInfo, bool>, Expression<Func<CastInfo, bool>>). ?

, #. PredicateBuilder.New<T> ExpressionStarter<T>, , Expression, , Expression<Func<T, bool>> Func<CastInfo, bool>. Enumerable/Queryable lambda func/expression. , , , - complier - n.CastInfo.Any((Func<CastInfo, bool>)castCondition), , , .

LinqKit AsExpandable , "" Invoke, "" . , , Expression<Func<CastInfo, bool>>, :

_context.Name.AsExpandable().Where(n => n.CastInfo.Any(c => castCondition.Invoke(c)));

, . Expression<Func<T, bool> :

Expression<Func<CastInfo, bool>> castPredicate = castCondition;

_context.Name.AsExpandable().Where(n => n.CastInfo.Any(c => castPredicate.Invoke(c)));

_context.Name.AsExpandable().Where(n => n.CastInfo.Any(castPredicate.Compile()));

, , :

using System;
using System.Linq.Expressions;

namespace LinqKit
{
    public static class Extensions
    {
        public static Expression<Func<T, bool>> ToExpression<T>(this ExpressionStarter<T> expr) => expr;
    }
}

var castPredicate = castCondition.ToExpression();

- , .. :

_context.Name.AsExpandable().Where(n => n.CastInfo.Any(c => castCondition.ToExpression().Invoke(c)));
+4

Source: https://habr.com/ru/post/1687361/


All Articles