Hibernate和Equality检查延迟加载的对象

时间:2015-03-06 14:53:27

标签: c# hibernate lazy-loading equality

我对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;
  }

2 个答案:

答案 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策略对我来说看起来并不乐观。代理的原始问题与它们的包装对象相比似乎可以解决。