我认为实体应该默认通过主键比较实现相等,但是 nhibernate 文档建议使用业务标识:
最明显的方法是通过比较两个对象的标识符值来实现 Equals()/GetHashCode()。如果值相同,则两者必须是同一数据库行,因此它们相等(如果将两者都添加到 ISet,则 ISet 中将只有一个元素)。不幸的是,我们不能使用这种方法。NHibernate 只会将标识符值分配给持久的对象,新创建的实例不会有任何标识符值!我们建议使用业务键相等来实现 Equals() 和 GetHashCode()。
业务键相等意味着 Equals() 方法仅比较形成业务键的属性,该键将识别我们在现实世界中的实例(自然候选键)
还有这个例子(也来自文档):
public override bool Equals(object other)
{
if (this == other) return true;
Cat cat = other as Cat;
if (cat == null) return false; // null or not a cat
if (Name != cat.Name) return false;
if (!Birthday.Equals(cat.Birthday)) return false;
return true;
}
这让我头晕目眩,因为业务标识的概念(根据示例)与语法比较相同,这基本上是我与 ValueObjects 相关联的语义类型。不使用数据库主键作为比较值的原因是因为如果主键不是在客户端生成(例如增量)并且您使用某种哈希表集合(例如 ISet),这将更改对象的哈希码用于存储您的实体。
如何创建一个不违反相等/哈希码 ( http://msdn.microsoft.com/en-us/library/bsc2ak47.aspx ) 的一般规则并符合 nhibernate 规则的良好相等实现?