Howto use predicates in LINQ to Entities for Entity Framework objects

醉酒当歌 提交于 2019-11-27 21:12:32

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

Methods used in Linq to Entities must be canonically mapped by the Linq provider in order to work. Since the Linq provider, EF in your case, was unable to map your predicate to an internal method, it threw an error.

For LINQ scenarios, queries against the Entity Framework involve mapping certain CLR methods to methods on the underlying data source through canonical functions. Any method calls in a LINQ to Entities query that are not explicitly mapped to a canonical function will result in a runtime NotSupportedException exception being thrown

Source: CLR Method to Canonical Function Mapping (http://msdn.microsoft.com/en-us/library/bb738681.aspx)

You can try to take those methods that ARE mapped and chain them into your Linq expression, or use a stored procedure. But until EF supports all of the CLR, you will be left with having to find a work-around.

On the plus side, each release seems to add a bit more to the canonical list.

Worth reading as a possible work-around: http://msdn.microsoft.com/en-us/library/dd456857.aspx

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!