我对hibernate有一些乐趣。像这样的函数:
public class Key
{
public virtual bool IsEqual(Key key)
{
return this == key;
}
}
如果参数与调用IsEqual的实例相同,可以期望此函数始终返回true:
Assert.IsTrue(MyKey.IsEqual(MyKey));
但只有实例“myKey”不是延迟加载的对象/代理才会出现这种情况。 KeyProxy会将该调用委托给包装的内部Key对象,这会导致包装对象与Proxy对象进行比较(后者将失败)。
基本上,这里也讨论过:NHibernate, proxies and equality
解决方案有点令人失望。覆盖等于比较主键属性的缺点是它只适用于已经有值的对象,而新对象在保存之前没有主键值。我可以尝试强制新对象直接接收有效的主键值,但这听起来不是处理这个问题的好方法。
是否有更好(更一般)的方法来处理这种情况?不会重写Equals并与一个独特的(非持久的)属性进行比较就行了吗?
那样的东西?
public object Identifier {get; private set;}
public Key()
{
Identifer = new object();
}
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
Key k = obj as Key;
if (k == null)
{
return false;
}
return this.Identifier == key.Identifier;
}
答案 0 :(得分:1)
为了克服这个问题和其他问题,例如使用标识列作为主键,我们向域模型的基类添加了GUID,对象创建由工厂类处理,为每个实体提供GUID,这是然后坚持作为实体的一部分。
然后使用GUID比较实体,基本上我们在Equals()和GetHashCode()方法中使用它。
public override int GetHashCode()
{
return this.EqualityIdentifier.GetHashCode();
}
public override bool Equals(object obj)
{
IDomainObject Obj = obj as IDomainObject
if (Obj == null)
{
return false;
}
return this.EqualityIdentifier == Obj.EqualityIdentifier;
}
答案 1 :(得分:0)
为了对性能产生最小的影响,我决定使用一个非持久的readonly int属性“Identifier”,它由一个小的静态和线程安全的数字生成器方法填充(懒惰/第一次访问)。
private static int _equalityIdentifierSequence;
private static int GenerateEqualityIdentifier()
{
Interlocked.Increment(ref _equalityIdentifierSequence);
return _equalityIdentifierSequence;
}
我很满意这样一个事实,即从不同会话加载但代表同一实体的两个对象被视为“不相等”,因此GUID策略对我来说看起来并不乐观。代理的原始问题与它们的包装对象相比似乎可以解决。