我想比较记录以查看它们之间是否存在差异。
Person
桌子:
ID Name Address
--------------------------------
1 John Smith 123 A Street
2 John Smith 123 A Street
3 John Smith 234 B Street
记录1和2是“相等的”。记录2和3是“不相等”。
我已经IEquatable
在模型上实现了Person
如下。
public static bool operator ==(Person p1, Person p2)
{
if (System.Object.ReferenceEquals(p1, p2)) return true;
return p1.Equals(p2);
}
public static bool operator !=(Person p1, Person p2)
{
return !(p1== p2);
}
public bool Equals(Person other)
{
if (System.Object.ReferenceEquals(this, other)) return true;
if (Name != other.Name) return false;
if (Address != other.Address) return false;
return true;
}
public override bool Equals(object obj)
{
Person person = obj as Person;
if (person == null) return false;
return Equals(person);
}
public override int GetHashCode()
{
unchecked
{
int hash = (int)2166136261;
hash = hash * 25165843 ^ (Name != null ? Name .GetHashCode() : 0);
hash = hash * 25165843 ^ (Address != null ? Address.GetHashCode() : 0);
return hash;
}
}
问题是,Persons
实现导航属性中的ICollection时。它缺少彼此“相等”的记录(即返回单个John Smith 123 A Street记录)。我猜这是因为默认情况下,它会考虑具有唯一主键的不同实体。通过覆盖等于,它认为两条记录都是同一实体。
屏幕截图显示为Addresses
而不是Persons
:(顶部为带IEquatable
,底部为不带)
//Addresses Definition (generated code)
public virtual ICollection<Address> Addresses { get; set; }
我如何调和需要在对象级别看到平等的EF与我想看到逻辑相等的EF?
关键似乎在EF源代码中
在的注释中EntityUtil.DetermineCollectionType(Type requestedType)
,有以下“规则”:
// The rules are:
// If the collection is defined as a concrete type with a publicly accessible parameterless constructor, then create an instance of that type
// Else, if HashSet{T} can be assigned to the type, then use HashSet{T}
// Else, if List{T} can be assigned to the type, then use List{T}
// Else, throw a nice exception.
因此,由此看来,EF将为HashSet<Address>
您的导航属性添加一个新的。这将使用默认的相等比较器,并防止添加任何重复项。当您的Equals
实现将您的两个结果均等时,将仅包含其中一个。
实体通常是唯一标识的-Equals
忽略唯一标识符的覆盖可能不正确。最好的解决方案是删除覆盖并实施单独的IEqualityComparer
。大多数使用相等语义的方法都将其作为参数。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句