2015-03-19 226 views
0

在下面的查询中,Distinct调用似乎并没有被做任何事情:为什么Distinct不能在这个LINQ查询中工作?

using (var db = new AccountsDbContext()) 
{ 
    var uniques = db.AccountMappings 
     .Select(m => new CanvasAccount { UserName = m.CanvasUser, Password = m.CanvasPassword }) 
     .OrderBy(m => m.UserName) 
     .ToList() 
     .Distinct(new CanvasAccountComparer()); 
    accounts.AddRange(uniques); 
} 

该查询返回三个CanvasAccount对象,但有两个那些具有完全相同的用户名和密码。我的比较器如下:

class CanvasAccountComparer : IEqualityComparer<CanvasAccount> 
{ 
    public bool Equals(CanvasAccount x, CanvasAccount y) 
    { 
     return (x.UserName.ToLower() == y.UserName.ToLower()) && (x.Password == y.Password); 
    } 

    public int GetHashCode(CanvasAccount obj) 
    { 
     return obj.GetHashCode(); 
    } 
} 
+0

我推荐使用'ToLowerInvariant'而不是'ToLower' – CodesInChaos 2015-03-19 08:49:03

回答

4

您的比较器坏了 - 两个相等的对象不一定返回相同的哈希码。平等和哈希码生成必须相互一致。你可以解决这个使用类似:

public int GetHashCode(CanvasAccount obj) 
{ 
    int hash = 23; 
    hash = hash * 31 + obj.UserName.ToLower().GetHashCode(); 
    hash = hash * 31 + obj.Password.GetHashCode(); 
    return hash; 
} 

注:

  • 使用ToLower()是不是真的执行不区分大小写的比较的好方法。这里有各种各样的古怪文化。理想情况下,请使用StringComparer
  • 上面的代码假定PasswordUserName都将是非空的。如果其中任何一个都可以为空,则需要检查这一点。
  • 我希望这段代码并不意味着你在使用纯文本密码。请注意,如果密码是hashd和salted,则两个相同的纯文本密码可能会有不同的哈希值。
+0

感谢Jon。我必须承认,用一张红脸,我实际上大声想,“如果他们的领域是相同的,哈希码应该是。”我总是意识到安全性,并且密码哈希算法返回的是不同的值,但有点急于查看概念证明,因为大约3小时前我给出了一个要求。 – ProfK 2015-03-19 08:35:29

相关问题