2015-03-19 227 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

相關問題