In the query below, the Distinct
call doesn't seem to be doing anything:
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);
}
This query returns three CanvasAccount
objects, but two of those have exactly the same username and password. My comparer is as follows:
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();
}
}
Your comparer is broken - two objects which are equal don't necessarily return the same hash code. Equality and hash code generation have to be consistent with each other. You can fix this using something like:
public int GetHashCode(CanvasAccount obj)
{
int hash = 23;
hash = hash * 31 + obj.UserName.ToLower().GetHashCode();
hash = hash * 31 + obj.Password.GetHashCode();
return hash;
}
Note:
ToLower()
isn't really a good way of performing case-insensitive comparisons. There are all kinds of oddities around culture here. Ideally, use StringComparer
instead.Password
and UserName
will both be non-null. If either can be null, you'll need to check for that.See more on this question at Stackoverflow