Why does List(T).Contains fail to find matches on lists of Entity Framework objects?
I've got two lists of "Customer" objects, generated from Entity Framework. I need to compare the two lists to see if there are any differences between them so, naturally, I wrote something like this:
private static List<Customer> originalList;
public static bool TestForEQ(List<Customer> source, List<Customer> destination)
{
foreach(Customer cust in originalList) {
if( !currentList.Contains(cust) )
{
return false;
}
}
public static void CheckData()
{
var ctx = new CustomersEntities();
if(originalList == null)
{
originalList = ctx.Customers.ToList<Customer>();
}
else
{
bool equiv = testForEQ(originalList, ctx.Customers.ToList<Customer>());
originalList = ctx.Customers.ToList<Customer>()
}
}
CheckData is call开发者_StackOverflow中文版ed periodically from a Thread.
So when I stepped through it for the first time, before making any changes to the database between when originalList and currentList were generated, I was surprised to find that the two initial objects in the list were not - according to Contains() - equivalent and that the above code returned false.
I have verified that the basic properties of the two objects (Id, name etc) are equivalent and that no pair of objects from either list are treated as equivalent by Contains(), so ..
1) Can anyone help me find out what property(ies) of two apparently identical data objects are causing Contains() to fail on?
2) Does anyone know of anything on entity framework which would cause two generated entities to not be equivalent if fetched from an untouched data table at different times? Is there a timestamp of some sort? Or are they treated as references?
Because, by default, you're checking reference equality...and that is failing.
To be sure you get the results you expect, you can create a custom comparer (by implementing IEqualityComparer<T>
) and provide that to the Contains()
method.
For example, the following implementation would compare Customers based on their Id:
public class CustomerEqualityComparer : IEqualityComparer<Customer>
{
public bool Equals(Customer c1, Customer c2)
{
return c1.Id == c2.Id;
}
public int GetHashCode(Customer c)
{
return c.Id.GetHashCode();
}
}
Then you could call Contains with:
if(!currentList.Contains(cust, new CustomerEqualityComparer())
return false;
精彩评论