2010-01-20 36 views
4

我有我想要的一个子集进行比较和判断来选择之外的所有子集的实体。使用的的IEqualityComparer与LINQ to实体除外条款

所以,我的查询看起来是这样的:它执行一些任务后

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.IEnumerable 1[UnitedOne.Data.Sql.Product], System.Collections.Generic.IEqualityComparer 1 [UnitedOne.Data.Sql.Product])” 方法,和叔他的方法不能将 翻译成商店表达式。

回答

7

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

在幕后,它编码与运营商和常用的功能是如何运作的知识,以及这些涉及到TSQL。问题是L2E的开发人员不知道你是如何实现IEqualityComparer的。因此,他们想不通的是,当你说A类== B类你的意思是(例如)“在哪里Person.FirstName ==名字和Person.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 

显然,这将跨线带来更多的数据和更多内存密集型。第一种选择通常是最好的。

+0

感谢您的建议。在这种情况下,我们只谈不到100行,所以我认为第二种选择并不是那么糟糕。我可能会缓存结果只是为了加快未来的寻求。谢谢! – 2010-01-20 18:23:58

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

    ... 
} 
+0

嘿Slaks,你能说说使用IEqualityComparer作为单例吗?性能或其他原因?因为我在使用IEqualityComparer查找单例时遇到问题,即使在MSDN文档中也是如此。 – mare 2010-05-16 10:33:57

+1

@Mare:由于各个实例之间没有区别,因此多个实例无关紧要。 – SLaks 2010-05-16 16:34:19

2

IEqualityComparer<T>只能在本地执行,所以不能转换为SQL命令,因此,错误