C# 将LinqKit PredicateBuilder用于相关模型(EF Core)
我想使用LinqKit的PredicateBuilder,并将谓词传递到相关模型的C# 将LinqKit PredicateBuilder用于相关模型(EF Core),c#,linq,.net-core,entity-framework-core,linqkit,C#,Linq,.net Core,Entity Framework Core,Linqkit,我想使用LinqKit的PredicateBuilder,并将谓词传递到相关模型的.Any方法中 所以我想构建一个谓词: var castCondition = PredicateBuilder.New<CastInfo>(true); if (movies != null && movies.Length > 0) { castCondition = castCondition.And(c => movies.Contains(c.MovieI
.Any
方法中
所以我想构建一个谓词:
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);
}
IQueryable<Name> result = _context.Name.AsExpandable().Where(n => n.CastInfo.Any(castCondition));
return await result.OrderBy(n => n.Name1).Take(25).ToListAsync();
或者直接使用compile
IQueryable<Name> result = _context.Name.AsExpandable().Where(n => n.CastInfo.Any(castCondition.Compile()));
所以我想我只是错过了一些关于建设者的东西
关于版本的更新:我使用dotnet core 2.0和LinqKit.Microsoft.EntityFrameworkCore 1.1.10查看代码,可以假定
castCondition
变量的类型是Expression
(与早期版本的PredicateBuilder
一样)
但是如果是这种情况,那么n.CastInfo.Any(castCondition)
甚至不应该编译(假设CastInfo
是一个集合导航属性,那么编译器将点击可枚举。任何需要Func
,而不是表达式的)。这是怎么回事
在我看来,这是C#隐式运算符滥用的一个很好的例子。PredicateBuilder.New
方法实际上返回一个名为的类,该类有许多方法模拟Expression
,但更重要的是,它有到Expression
和Func
的隐式转换。后者允许该类用于顶级可枚举
/可查询
方法,以替换相应的lambda func/表达式。但是,它还可以防止在表达式树中使用时出现编译时错误,就像在您的例子中一样-编译器会发出类似n.CastInfo.Any((Func)castCondition)
的消息,这当然会在运行时导致异常
LinqKitAsExpandable
方法的整个思想是允许通过自定义Invoke
扩展方法“调用”表达式,然后在表达式树中“展开”。因此,在开始时,如果变量类型是Expression
,则预期用途是:
_context.Name.AsExpandable().Where(n => n.CastInfo.Any(c => castCondition.Invoke(c)));
但由于前面解释的原因,现在无法编译。因此,您必须首先将其转换为表达式感谢您的详细解释。我尝试了您的代码,但不幸的是,我收到了一个警告无法翻译LINQ表达式“where u castCondition_0.Invoke([c]),它将在本地进行计算。
因此,在编译和运行时,该条件不会添加到SQL中,并且查询会选择所有行。你有什么建议吗?实际上你提到了ExpressionStarter
可以转换为Expression
。因此,这起作用var castExpr=(表达式)castCondition;context.Name.AsExpandable().Where(n=>n.CastInfo.Any(castExpr.Compile()).Count()
;内联由于某些原因变量不起作用内联不起作用,因为“扩展器”无法识别ExpressionStarter.Compile()
。听起来像是不完整的LinqKit作业:(啊,这就是让我留在这里的Q&A类型!(我有时想退出)。上面的建议对我也起了作用。我收到了另一个错误,暗示与async/await的组合不可能。在应用上述提示并删除await和To…async()之后,所有这些都很好。谢谢!
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();
_context.Name.AsExpandable().Where(n => n.CastInfo.Any(c => castCondition.Invoke(c)));
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)));