使用的IEqualityComparer与LINQ to实体除外条款
-
21-09-2019 - |
题
我有我想和一个子集进行比较,并确定选择除了所述子集的所有的实体。
所以,我的查询如下所示:
Products.Except(ProductsToRemove(), new ProductComparer())
在ProductsToRemove()
方法返回它执行几个任务之后的List<Product>
。所以在它的最简单的形式是上述
在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实体无法识别 方法 “System.Linq.IQueryable
1[UnitedOne.Data.Sql.Product] Except[Product](System.Linq.IQueryable
1 [UnitedOne.Data.Sql.Product] System.Collections.Generic.IEnumerable1[UnitedOne.Data.Sql.Product], System.Collections.Generic.IEqualityComparer
1 [UnitedOne.Data.Sql.Product])” 方法,并且该方法不能 翻译成商店表达。
解决方案
LINQ实体实际上没有执行查询,它是口译你的代码,将其转换为TSQL,然后执行在服务器上。
在内部,它是编码与运营商和共同功能如何工作的知识,以及这些涉及TSQL。问题是,L2E开发商不知道你究竟是如何实现的IEqualityComparer。因此,它们不能弄清楚的是,当你说一类乙你==类意味着(例如)“在哪里Person.FirstName == FirstName和Person.LastName ==名字”。
所以,当L2E解释撞击它不能识别的方法,它引发此异常。
有两种方法可以解决这个问题。首先,制定了凡(),它满足您的要求,平等但不依赖于任何自定义的方法。换句话说,测试而不是上equals类中定义的方法实例的属性的相等性。
其次,你可以触发查询的执行,然后在内存中做你的比较。例如:
var notThisItem = new Item{Id = "HurrDurr"};
var items = Db.Items.ToArray(); // Sql query executed here
var except = items.Except(notThisItem); // performed in memory
显然,这将带来跨线更多的数据和更内存密集型。第一种选择通常是最好的。
其他提示
您正在试图将Except
调用转换与您的自定义IEqualityComparer
到实体SQL。
显然,你的类不能被转换成SQL。
您需要编写Products.AsEnumerable().Except(ProductsToRemove(), new ProductComparer())
,迫使它在客户端上执行。请注意,这将下载所有的产品从服务器。
顺便说一句,你ProductComparer
类应该是一个单身,像这样的:
public class ProductComparer : IEqualityComparer<Product> {
private ProductComparer() { }
public static ProductComparer Instance = new ProductComparer();
...
}
在IEqualityComparer<T>
只能在本地执行的,它不能被转换为SQL命令,因此误差