为什么EqualityComparer <string> .Default不起作用?</string>

时间:2013-12-25 05:44:00

标签: entity-framework linq-to-entities iequalitycomparer

var dic = context.Treasure.Include("TreasureShare")
  .Where(t => t.TreasureShare.IsShared && t.TreasureShare.EvaluationContent.Contains(keyword))
  .ToDictionary(t => t.ProductUrl, t => t.ProductId, EqualityComparer<string>.Default);

我收到了一个错误:

  

已添加具有相同键的项目。

那么为什么equalcomparer不起作用,以及如何在查询数据库时使用equalitycomparer来获取不同的记录。

更新

我知道IEqualityComparer只能在本地执行,但我没有收到如下错误:

  

LINQ to Entities无法识别方法'System.Linq.IQueryable 1[Panli.Service.Share.DataAccess.DbData.Treasure] Distinct[Treasure](System.Linq.IQueryable 1 [Panli.Service.Share.DataAccess.DbData.Treasure],System.Collections.Generic.IEqualityComparer`1 [Panli.Service .Share.DataAccess.DbData.Treasure])'方法,并且此方法无法转换为商店表达式。

除了我将代码更改为以下内容:

dic = context.Treasure.Include("TreasureShare")
  .Where(t => t.TreasureShare.IsShared && t.TreasureShare.EvaluationContent.Contains(theme))
  .Distinct(new TreasureEqualityComparer()).ToDictionary(t => t.ProductUrl, t => t.ProductId);

这是我的TreasureEqualityComparer:

public class TreasureEqualityComparer : EqualityComparer<Treasure>
{
    public override bool Equals(Treasure x, Treasure y)
    {
        return x.ProductUrl.ToLower() == y.ProductUrl.ToLower();
    }

    public override int GetHashCode(Treasure obj)
    {
        return obj.ProductUrl.ToLower().GetHashCode();
    }
}

那么,当我使用具有Distinct()参数的ToDictionary(..)时,为什么不像IEqualityComparer那样抛出异常?任何人都可以解释一下吗?

2 个答案:

答案 0 :(得分:1)

  

那为什么不抛出异常?

ToDictionary部分在内存中执行。当您调查执行的SQL时,这一点很明显:没有任何内容显示转换为Dictionary的任何准备工作。

另一方面,Distinct的查询表达式被整体翻译成SQL(除了它不是因为它失败)。 EF试图让数据库完成返回不同值的艰苦工作,但当然比较器无法转换为SQL,因此不支持Distinct()的重载。

关于重复键:显然有重复的URL(忽略大小写)。也许你应该使用group by

答案 1 :(得分:0)

字典键必须是唯一的。在这种情况下,您使用ProductUrl作为字典键,使用ProductId作为值,遗憾的是,错误表明Table中有多个记录具有相同的ProductUrl。所以你不能将它用作字典键。