结合使用IEqualityComparer和LINQ to Entities Except子句 [英] Using an IEqualityComparer with a LINQ to Entities Except clause

查看:124
本文介绍了结合使用IEqualityComparer和LINQ to Entities Except子句的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个实体想与一个子集进行比较,并确定选择除该子集以外的所有实体.

I have an entity that I'd like to compare with a subset and determine to select all except the subset.

所以,我的查询看起来像这样:

So, my query looks like this:

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

ProductsToRemove()方法在执行一些任务后返回List<Product>.因此,最简单的形式就是上面的内容.

The ProductsToRemove() method returns a List<Product> after it performs a few tasks. So in it's simplest form it's the above.

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

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

However, I continually receive the following exception:

LINQ to Entities无法识别 方法 '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])' 方法,并且该方法不能是 转换为商店表达式.

LINQ to Entities does not recognize the method 'System.Linq.IQueryable1[UnitedOne.Data.Sql.Product] Except[Product](System.Linq.IQueryable1[UnitedOne.Data.Sql.Product], System.Collections.Generic.IEnumerable1[UnitedOne.Data.Sql.Product], System.Collections.Generic.IEqualityComparer1[UnitedOne.Data.Sql.Product])' method, and this method cannot be translated into a store expression.

推荐答案

Linq to Entities实际上不是在执行查询,而是在解释您的代码,将其转换为TSQL,然后在服务器.

Linq to Entities isn't actually executing your query, it is interpreting your code, converting it to TSQL, then executing that on the server.

在幕后,将使用运算符和公用功能如何操作以及它们与TSQL的关系知识进行编码.问题在于L2E的开发人员不知道您实现IEqualityComparer的精确程度.因此,他们无法弄清楚当您说Class A == Class B时是指(例如)"Where Person.FirstName == FirstName AND Person.LastName == LastName".

Under the covers, it is coded with the knowledge of how operators and common functions operate and how those relate to TSQL. The problem is that the developers of L2E have no idea how exactly you are implementing IEqualityComparer. Therefore they cannot figure out that when you say Class A == Class B you mean (for example) "Where Person.FirstName == FirstName AND Person.LastName == LastName".

因此,当L2E解释器遇到无法识别的方法时,它将引发此异常.

So, when the L2E interpreter hits a method it doesn't recognize, it throws this exception.

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

There are two ways you can work around this. First, develop a Where() that satisfies your equality requirements but that doesn't rely on any custom method. In other words, test for equality of properties of the instance rather than an Equals method defined on the class.

第二,您可以触发查询的执行,然后在内存中进行比较.例如:

Second, you can trigger the execution of the query and then do your comparisons in memory. For instance:

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

显然,这将带来更多的数据通过线和更多的内存.通常,第一种选择是最好的.

Obviously this will bring much more data across the wire and be more memory intensive. The first option is usually the best.

这篇关于结合使用IEqualityComparer和LINQ to Entities Except子句的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆