5

我有一个实体,我想与一个子集进行比较,并决定选择除子集之外的所有实体。

因此,我的查询如下所示:

Products.Except(ProductsToRemove(), new ProductComparer())

ProductsToRemove()方法List<Product>在执行一些任务后返回 a 。所以最简单的形式就是上面的。

该类ProductComparer()如下所示:

public class ProductComparer : IEqualityComparer<Product>
{
    public bool Equals(Product a, Product b)
    {
        if (ReferenceEquals(a, b)) return true;

        if (ReferenceEquals(a, null) || ReferenceEquals(b, null))
            return false;

        return a.Id == b.Id;
    }

    public int GetHashCode(Product product)
    {
        if (ReferenceEquals(product, null)) return 0;
        var hashProductId = product.Id.GetHashCode();
        return hashProductId;
    }
}

但是,我不断收到以下异常:

LINQ to Entities 无法识别方法 'System.Linq.IQueryable 1[UnitedOne.Data.Sql.Product] Except[Product](System.Linq.IQueryable1[UnitedOne.Data.Sql.Product], System.Collections.Generic.IEnumerable 1[UnitedOne.Data.Sql.Product], System.Collections.Generic.IEqualityComparer1[UnitedOne.Data.Sql.Product])' 方法,并且此方法不能被翻译成商店表达式。

4

3 回答 3

8

Linq to Entities 实际上并没有执行您的查询,它正在解释您的代码,将其转换为 TSQL,然后在服务器上执行。

在幕后,它使用运算符和常用函数如何操作以及它们如何与 TSQL 相关的知识进行编码。问题是 L2E 的开发人员不知道您是如何实现 IEqualityComparer。Class A == Class B因此,当您说您的意思是(例如)时,他们无法弄清楚"Where Person.FirstName == FirstName AND Person.LastName == LastName"

因此,当 L2E 解释器遇到它无法识别的方法时,它会抛出此异常。

有两种方法可以解决此问题。首先,开发一个Where()满足您的平等要求但不依赖任何自定义方法的方法。换句话说,测试实例属性的相等性,而不是Equals类上定义的方法。

其次,您可以触发查询的执行,然后在内存中进行比较。例如:

var notThisItem = new Item{Id = "HurrDurr"};
var items = Db.Items.ToArray(); // Sql query executed here
var except = items.Except(notThisItem); // performed in memory

显然,这将通过网络带来更多的数据,并且会占用更多的内存。第一个选项通常是最好的。

于 2010-01-20T16:26:56.573 回答
4

您正在尝试将Except自定义调用转换IEqualityComparer为 Entity SQL。

显然,你的类不能转换成 SQL。

您需要编写Products.AsEnumerable().Except(ProductsToRemove(), new ProductComparer())以强制它在客户端上执行。请注意,这将从服务器下载所有产品。


顺便说一句,你的ProductComparer班级应该是一个单身人士,像这样:

public class ProductComparer : IEqualityComparer<Product> {
    private ProductComparer() { }
    public static ProductComparer Instance = new ProductComparer();

    ...
}
于 2010-01-20T16:20:51.980 回答
3

只能在IEqualityComparer<T>本地执行,不能翻译成SQL命令,所以报错

于 2010-01-20T16:21:39.020 回答