如何在实体框架对象的LINQ to Entities中使用谓词 [英] Howto use predicates in LINQ to Entities for Entity Framework objects

查看:159
本文介绍了如何在实体框架对象的LINQ to Entities中使用谓词的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我的目标是尽可能多地从数据库中过滤,而不需要数据库中的实体框架对象将过滤逻辑应用于内存中的结果。



为此,业务逻辑层将谓词传递给数据访问层。我的意思是

  Func&MyEntity,bool> 

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

  public IQueryable&MyEntity> GetAllMatchedEntities(Func< MyEntity,Boolean> isMatched)
{
return qry = _Context.MyEntities.Where(x => isMatched(x));
}

我收到例外


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


这个问题 建议使用AsalPandable()方法从 LINQKit 库。



但是再次使用

  public IQueryable< MyEntity> GetAllMatchedEntities(Func< MyEntity,Boolean> isMatched)
{
return qry = _Context.MyEntities.AsExpandable()。其中​​(x => isMatched(x));
}

我收到例外


无法将类型为
'System.Linq.Expressions.FieldExpression'的对象键入
'System.Linq.Expressions.LambdaExpression'


有没有办法在LINQ to Entities中查询Entity Framework对象使用谓词,以便将其正确转换为SQL语句。 >

谢谢。

解决方案

您不需要LinqKit来执行此操作。只需记住使用

 表达式< Func< MyEntity,bool>> 

而不是

 code> Func< MyEntity,bool> 

如下所示:

  public IQueryable&MyEntity> GetAllMatchedEntities(表达式< Func< MyEntity,Boolean>>谓词)
{
return _Context.MyEntities.Where(predicate);
}

您必须使用表达式,因为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)

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

  private readonly Expression< Func< MyEntity,bool>> IsMatch = x => x.Age> 18; 
...然后使用它
this.GetAllMatchedEntities(IsMatch)

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 }


I'm using LINQ to Entities for Entity Framework objects in my Data Access Layer.

My goal is to filter as much as I can from the database, without applying filtering logic to in-memory results.

For that purpose Business Logic Layer passes a predicate to Data Access Layer.

I mean

Func<MyEntity, bool>

So, if I use this predicate directly, like

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

I'm getting the exception

[System.NotSupportedException] --- {"The LINQ expression node type 'Invoke' is not supported in LINQ to Entities."}

Solution in that question suggests to use AsExpandable() method from LINQKit library.

But again, using

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

I'm getting the exception

Unable to cast object of type 'System.Linq.Expressions.FieldExpression' to type 'System.Linq.Expressions.LambdaExpression'

Is there way to use predicate in LINQ to Entities query for Entity Framework objects, so that it is correctly transformed it into a SQL statement.

Thank you.

解决方案

You don't need LinqKit to do this. Just remember to use

Expression<Func<MyEntity, bool>>

instead of

Func<MyEntity, bool>

Something like this:

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

You have to use Expression because Linq to Entities needs to translate your lambda to SQL.

When you use Func your lambda is compiled to IL but when using Expression it is an expression tree that Linq to Entities can transverse and convert.

This works with expressions that Linq to Entities understands.

If it keeps failing then your expression does something that Linq to Entities can not translate to SQL. In that case I don't think LinqKit will help.

Edit:

There is no conversion needed. Just define the method GetAllMatchedEntities with an Expression parameter and use it in the same way you would with a Func parameter. The compiler does the rest.

There are three ways you can use GetAllMatchedEntities.

1) With an inline lambda expression:

this.GetAllMatchedEntities(x => x.Age > 18)

2) Define your Expression as a field (can be a variable also)

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

3) You can create your expression manually. The downsize is more code and you miss the compile-time checks.

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);
}

这篇关于如何在实体框架对象的LINQ to Entities中使用谓词的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆