【发布时间】:2015-01-15 06:24:08
【问题描述】:
我想比较记录,看看它们之间是否存在差异。
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 “不相等”。
我已经在模型Person 上实现了IEquatable,如下所示。
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;
}
}
问题是当导航属性中的PersonsICollection 实现时。它缺少彼此“相等”的记录(即返回单个 John Smith 123 A Street 记录)。我猜这是因为默认情况下它会考虑具有唯一主键的不同实体。通过覆盖 equals 它认为两条记录是同一个实体。
显示Addresses 而不是Persons 的屏幕截图:(顶部是IEquatable,底部是没有)
//Addresses Definition (generated code)
public virtual ICollection<Address> Addresses { get; set; }
我如何协调 EF 需要在对象级别查看平等与我希望看到逻辑平等?
【问题讨论】:
-
你能在
EmployeeElection上显示Addresses属性的声明吗? -
@CharlesMager 当然,我已经在屏幕截图下添加了它。它是生成的 EF 代码的一部分。
-
你在构造函数中设置为
new Hashset<Address>()吗?在 EF 样本中经常出现这种情况。另外,virtual关键字允许延迟加载,创建的 EF 代理可能使用ISet<Address>(我不知道具体情况!)。设置语义意味着无法添加重复项,并且默认情况下它们将使用默认的相等比较器(因此您的Equals覆盖)。因此,尽管查询可能返回重复项,但模型/EF 不会显示它们。 -
@CharlesMager 不,我没有在构造函数中设置任何东西。
ISet很有趣,这可以解释我的问题。 -
@CharlesMager I found something on that 它说如果虚拟属性由
ICollection类型支持,那么他们会将List放入其中。当然这是来自 EF4,我不确定它是否从 EF6 改变。
标签: c# entity-framework entity-framework-6 equality iequatable