Equals和GetHashCode中的延迟加载的NHibernate属性

Ria*_*its 5 c# nhibernate lazy-loading

如何处理以下问题?

我们正在使用延迟加载的NHibernate属性,每当我们调用Equals()或使用GetHashCode()任何属性时,都会延迟加载,可能导致一连串的延迟加载操作.可以使用急切加载作为替代方案,但我认为仅在特定情况下而不是作为一般解决方案.

典型情况如下:

public class AbstractSaveableObject {
    [Id(0, Name = "Id", UnsavedValue = null)]
    [Generator(1, Class = "native")]
    public virtual long? Id { get; set; }
}

[Class(NameType = typeof(ClassA))]
public class ClassA : AbstractSavableObject {
    [Bag(0, Inverse = true, Cascade = "none")]
    [Key(1, Column = "ClassA")]
    [OneToMany(2, ClassType = typeof(ClassB))]
    public virtual ICollection<ClassB> ClassBs { get; set; }
}

[Class(NameType = typeof(ClassB))]
public class ClassB : AbstractSavableObject {

    [ManyToOne(Column = "ClassA")]
    public virtual ClassA ClassA { get; set; }

    [ManyToOne]
    public virtual ClassC ClassC { get; set; }

    [ManyToOne]
    public virtual ClassD ClassD { get; set; }

    public virtual bool Equals(ClassB other)
    {
        if (ReferenceEquals(null, other))
        {
            return false;
        }
        if (ReferenceEquals(this, other))
        {
            return true;
        }
        return Equals(other.ClassC, ClassC) && Equals(other.ClassD, ClassD);
    }
}
Run Code Online (Sandbox Code Playgroud)

为简洁起见GetHashCode,Equals(object)已经实施并且已经省略.

可以用什么策略来解决这个问题?

asg*_*las 10

如果两个实体属于同一类型且具有相同的主键,则它们是相等的.

如果你有键的整数:

  1. 像现在一样检查参考相等性
  2. 如果在某些基类中使用Equal方法,则检查您比较的类型是否相等.在这里你可以遇到代理问题,我会回到那里
  3. 检查主键是否相等 - 这不会导致任何延迟加载

如果您有密钥的GUID:

  1. 像现在一样检查参考相等性
  2. 检查主键是否相等 - 这不会导致任何延迟加载

如果我有键的整数,我通常在我的实体的基类中有类似的Equal-override:

public virtual bool Equals(EntityBase other)
{
    if (other == null)
    {
        return false;
    }

    if (ReferenceEquals(other, this))
    {
        return true;
    }

    var otherType = NHibernateProxyHelper.GetClassWithoutInitializingProxy(other);
    var thisType = NHibernateProxyHelper.GetClassWithoutInitializingProxy(this);
    if (!otherType.Equals(thisType))
    {
        return false;
    }

    bool otherIsTransient = Equals(other.Id, 0);
    bool thisIsTransient = Equals(Id, 0);
    if (otherIsTransient || thisIsTransient)
        return false;

    return other.Id.Equals(Id);
}
Run Code Online (Sandbox Code Playgroud)

现在,如果您使用每个层次结构的表继承其他实体,您将面临如下问题:GetClassWithoutInitializingProxy将返回层次结构的基类(如果它是代理),如果它是加载的实体则返回更具体的类型.在一个项目中,我通过遍历层次结构来解决这个问题,因此总是比较基本类型 - 代理与否.

在这些日子里,虽然我总是会使用GUID作为键,并按照此处的描述进行操作:http://nhibernate.info/doc/patternsandpractices/identity-field-equality-and-hash-code.html

然后没有代理类型不匹配问题.