不断收到“的LINQ EX pression节点类型”调用“不支持LINQ到实体”异常

问题描述:

我使用C#(包括LINQ)来开发Web应用程序。我写了一个通用的方法来扩展任何实体的Get方法。然而,当我得到的运行时异常调用不支持LINQ到实体执行code当'的LINQ EX pression节点类型。下面是code:

I am using C# (including Linq) to develop a web application. I have written a generic method to extend Get method of any entity. However when I get the runtime exception 'The LINQ expression node type 'Invoke' is not supported in LINQ to Entities' when the code is executed. Below is the code:

using System.Linq;
using System.Linq.Expressions;
using LinqKit;

public static class ServiceExtension
{
    public static IEnumerable<T> GetActive<T>(this ICrudService<T> crudService, Expression<Func<T, bool>> where)
        where T : class, IDeletable
    {
        return crudService.Get(where.And(w => !w.IsDeleted));
    }
}

有人能告诉我什么,我做错了什么?

Can someone please tell me what I am doing wrong?

您正在使用LinqKit,这将仅适用于那些有 AsExpandable()呼吁queryables他们。这将包装的基本查询提供并翻译所有调用调用(其中用内部)弄成了查询供应商就明白了。

You're using LinqKit, which will only work on queryables that have had AsExpandable() called on them. This will wrap the underlying query provider and translate all calls to Invoke (which And is using internally) into something that the query provider will understand.

另一种方法是根本就没有使用LinqKit,并使用predicateBuilder以下的版本,可以与/或predicate EX pressions不依赖于使用的调用

The alternative would be to simply not use LinqKit, and use the following version of PredicateBuilder that can And/Or predicate expressions without relying on the use of Invoke:

public static class PredicateBuilder
{
    public static Expression<Func<T, bool>> True<T>() { return f => true; }
    public static Expression<Func<T, bool>> False<T>() { return f => false; }

    public static Expression<Func<T, bool>> Or<T>(
        this Expression<Func<T, bool>> expr1,
        Expression<Func<T, bool>> expr2)
    {
        var secondBody = expr2.Body.Replace(expr2.Parameters[0], expr1.Parameters[0]);
        return Expression.Lambda<Func<T, bool>>
              (Expression.OrElse(expr1.Body, secondBody), expr1.Parameters);
    }

    public static Expression<Func<T, bool>> And<T>(
        this Expression<Func<T, bool>> expr1,
        Expression<Func<T, bool>> expr2)
    {
        var secondBody = expr2.Body.Replace(expr2.Parameters[0], expr1.Parameters[0]);
        return Expression.Lambda<Func<T, bool>>
              (Expression.AndAlso(expr1.Body, secondBody), expr1.Parameters);
    }
}

相反,它依赖于下面的方法来取代一个EX pression所有的实例与另一:

It instead relies on the following method to replace all instance of one expression with another:

public static Expression Replace(this Expression expression,
    Expression searchEx, Expression replaceEx)
{
    return new ReplaceVisitor(searchEx, replaceEx).Visit(expression);
}

internal class ReplaceVisitor : ExpressionVisitor
{
    private readonly Expression from, to;
    public ReplaceVisitor(Expression from, Expression to)
    {
        this.from = from;
        this.to = to;
    }
    public override Expression Visit(Expression node)
    {
        return node == from ? to : base.Visit(node);
    }
}