如何在LINQ to Entities for Entity Framework对象中使用谓词

bai*_*rog 24 c# linq-to-entities entity-framework predicate linqkit

我在我的数据访问层中使用LINQ to Entities for Entity Framework对象.

我的目标是尽可能多地从数据库中过滤,而不将过滤逻辑应用于内存中的结果.

为此,业务逻辑层将谓词传递给数据访问层.

我的意思是

Func<MyEntity, bool>
Run Code Online (Sandbox Code Playgroud)

所以,如果我直接使用这个谓词,就像

public IQueryable<MyEntity> GetAllMatchedEntities(Func<MyEntity, Boolean> isMatched)
{
    return qry = _Context.MyEntities.Where(x => isMatched(x));
}
Run Code Online (Sandbox Code Playgroud)

我得到了例外

[System.NotSupportedException] --- {"LINQ to Entities中不支持LINQ表达式节点类型'Invoke'."}

该问题的解决方案建议使用LINQKit库中的AsExpandable()方法.

但是再次使用

public IQueryable<MyEntity> GetAllMatchedEntities(Func<MyEntity, Boolean> isMatched)
{
    return qry = _Context.MyEntities.AsExpandable().Where(x => isMatched(x));
}
Run Code Online (Sandbox Code Playgroud)

我得到了例外

无法将类型为"System.Linq.Expressions.FieldExpression"的对象强制转换为"System.Linq.Expressions.LambdaExpression"

有没有办法在LINQ to Entities查询实体框架对象中使用谓词,以便将其正确转换为SQL语句.

谢谢.

and*_*ort 45

您不需要LinqKit来执行此操作.只记得使用

Expression<Func<MyEntity, bool>>
Run Code Online (Sandbox Code Playgroud)

代替

Func<MyEntity, bool>
Run Code Online (Sandbox Code Playgroud)

像这样的东西:

public IQueryable<MyEntity> GetAllMatchedEntities(Expression<Func<MyEntity, Boolean>> predicate)
{
    return _Context.MyEntities.Where(predicate);
}
Run Code Online (Sandbox Code Playgroud)

您必须使用Expression,因为Linq to Entities需要将您的lambda转换为SQL.

当你使用Func时,你的lambda被编译为IL但是当使用Expression时,它是Linq to Entities可以横向和转换的表达式树.

这适用于Linq to Entities理解的表达式.

如果它一直失败,则表达式会执行Linq to Entities无法转换为SQL的操作.在那种情况下,我不认为LinqKit会有所帮助.

编辑:

无需转换.只需使用Expression参数定义GetAllMatchedEntities方法,并以与Func参数相同的方式使用它.编译器完成剩下的工作.

有三种方法可以使用GetAllMatchedEntities.

1)使用内联lambda表达式:

this.GetAllMatchedEntities(x => x.Age > 18)
Run Code Online (Sandbox Code Playgroud)

2)将表达式定义为字段(也可以是变量)

private readonly Expression<Func<MyEntity, bool>> IsMatch = x => x.Age > 18;
...then use it
this.GetAllMatchedEntities(IsMatch)
Run Code Online (Sandbox Code Playgroud)

3)您可以手动创建表达式.缩小尺寸是更多的代码,你错过了编译时检查.

public Expression<Func<MyEntity, bool>>  IsMatchedExpression()
{
    var parameterExpression = Expression.Parameter(typeof (MyEntity));
    var propertyOrField = Expression.PropertyOrField(parameterExpression, "Age");
    var binaryExpression = Expression.GreaterThan(propertyOrField, Expression.Constant(18));
    return Expression.Lambda<Func<MyEntity, bool>>(binaryExpression, parameterExpression);
}
Run Code Online (Sandbox Code Playgroud)

  • @ user274947我用你给出的例子编辑了我的答案. (2认同)
  • @ user274947你是对的,你几乎可以用同样的方式使用它.我添加了一些如何使用GetAllMatchedEntities的示例. (2认同)