代码之家  ›  专栏  ›  技术社区  ›  Jason N. Gaylord

将IEqualityComparer与LINQ to Entities Exception子句一起使用

  •  5
  • Jason N. Gaylord  · 技术社区  · 16 年前

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

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

    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 to实体无法识别 '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])” 方法,并且此方法不能为空

    3 回复  |  直到 16 年前
        1
  •  8
  •   anatol    6 年前

    LINQtoEntities实际上并不是在执行您的查询,而是在执行 将代码转换为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
    

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

        2
  •  4
  •   SLaks    16 年前

    Except IEqualityComparer

    显然,您的类不能转换为SQL。

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


    顺便说一下,你的 ProductComparer

    public class ProductComparer : IEqualityComparer<Product> {
        private ProductComparer() { }
        public static ProductComparer Instance = new ProductComparer();
    
        ...
    }
    
        3
  •  3
  •   Thomas Levesque    16 年前

    这个 IEqualityComparer<T>