繁体   English   中英

NHibernate事务提交或对象图回滚会抛出“ ObjectDisposedException”

[英]NHibernate transaction commit or rollback for an object graph throws 'ObjectDisposedException'

在尝试保存对象及其子对象时,NHibernate抛出

System.ObjectDisposedException: 'Cannot access a disposed object.'

当调用tx.Commit()

奇怪的是,数据仍然保留在数据库表中。

我的NHibernate会话通过以下方式与Web请求绑定

    if (!CurrentSessionContext.HasBind(sessionFactory))
        CurrentSessionContext.Bind(sessionFactory.OpenSession());

我正在使用ASP.NET MVC 5,NHibernate 4.1(尽管未使用流畅的NHibernate)

下面是产生错误的代码:

码:

    ISession session = SessionFactory.GetCurrentSession();            
    session.SetBatchSize(1000);
    using (var tx = session.BeginTransaction())
    {
        try
        {
            IList<Bar> barList = session.QueryOver<Bar>().Where(b => b.IsEnabled == true).List();

            foreach (Bar bar in barList)
            {
                var foo = new Foo { BarObj = bar };

                foo.BarDetailList = new HashSet<BarDetail>();
                foreach (Alpha alpha in bar.AlphaList)
                {
                    foreach (Beta beta in alpha.BetaList)
                    {
                        foo.BarDetailList.Add(
                            new BarDetail { ParentFoo = foo, AlphaObj = alpha, BetaObj = beta }
                        );
                    }
                }

                session.Persist(foo); // Save gives same result
            }
            tx.Commit(); // This line throws the ObjectDisposedException
        }
        catch (Exception ex)
        {
            // details omitted
            tx.Rollback();
        }
    }

类定义:

public class BarDetail : AuditableModelBase
{
    public virtual Foo ParentFoo { get; set; }
    public virtual Alpha alpha { get; set; }
    public virtual Beta beta { get; set; }
    public virtual IList<BarMonthlyDetail> MonthlyDetailList { get; set; }
    public override bool Equals(object obj)
    {
        if (obj == null)
            return false;

        var barDetail = obj as BarDetail;
        if (barDetail == null)
            return false;

        if (barDetail.Id.HasValue && barDetail.Id == this.Id)
            return true;
        else
        {
            // If id is null, then look for other members used when adding 
            // BarDetail objects as child objects at the time of creation of forecast
            // otherwise they wont get added
            if (this.alpha != null && barDetail.alpha != null && this.alpha.Id == barDetail.alpha.Id
                && this.beta != null && barDetail.beta != null && this.beta.Id == barDetail.beta.Id)
                return true;

        }

        return base.Equals(obj);
    }

    public override int GetHashCode()
    {
        unchecked
        {
            int hash = 17;

            hash = hash * 23 + Id.GetHashCode();
            return hash;
        }
    }
}

public class BarMonthlyDetail : AuditableModelBase
{
    public virtual BarDetail ParentBarDetail { get; set; }

    public override bool Equals(object obj)
    {
        if (obj == null)
            return false;

        var barMonthlyDetail = obj as BarMonthlyDetail;
        if (barMonthlyDetail == null)
            return false;

        if (barMonthlyDetail.Id == this.Id)
            return true;

        return base.Equals(obj);
    }

    public override int GetHashCode()
    {
        unchecked
        {
            int hash = 17;

            hash = hash * 23 + Id.GetHashCode();
            return hash;
        }
    }
}

public class Bar : AuditableModelBase
{
    public Bar()
    {
    }

    public virtual ISet<UserAccount> Users { get; set; }
    public virtual ISet<Alpha> alphas { get; set; }
    public virtual ISet<Beta> betas { get; set; }

    public override string ToString()
    {
        return Name ?? "";
    }

    public override bool Equals(object obj)
    {
        if (obj == null)
            return false;

        var bar = obj as Bar;
        if (bar == null)
            return false;

        if (bar.Id == this.Id)
            return true;

        return base.Equals(obj);
    }

    public override int GetHashCode()
    {
        unchecked
        {
            int hash = 17;

            hash = hash * 23 + Id.GetHashCode();
            //hash = hash * 23 + (Name ?? "").GetHashCode();
            //hash = hash * 23 + (Code ?? "").GetHashCode();
            return hash;
        }
    }
}

public class Foo : AuditableModelBase
{        
    public virtual Bar bar { get; set; }
    public virtual IList<BarDetail> BarDetailList { get; set; }

    public override string ToString()
    {
        return Name ?? "";
    }

    public override bool Equals(object obj)
    {
        if (obj == null)
            return false;

        var foo = obj as Foo;
        if (foo == null)
            return false;

        if (foo.Id == this.Id)
            return true;

        return base.Equals(obj);
    }

    public override int GetHashCode()
    {
        unchecked
        {
            int hash = 17;

            hash = hash * 23 + Id.GetHashCode();
            return hash;
        }
    }
}

public class Alpha : AuditableModelBase
{
    public virtual ISet<Bar> bars { get; set; }
    public virtual ISet<Beta> betas { get; set; }

    public override bool Equals(object obj)
    {
        if (obj == null)
            return false;

        var alpha = obj as Alpha;
        if (alpha == null)
            return false;

        if (alpha.Id == this.Id)
            return true;

        return base.Equals(obj);
    }

    public override int GetHashCode()
    {
        unchecked
        {
            int hash = 17;

            hash = hash * 23 + Id.GetHashCode();
            return hash;
        }
    }
}

public class Beta : AuditableModelBase
{

    public virtual Bar bar { get; set; }
    public virtual Alpha alpha { get; set; }

    public override string ToString()
    {
        return Name ?? "";
    }

    public override bool Equals(object obj)
    {
        if (obj == null)
            return false;

        var beta = obj as Beta;
        if (beta == null)
            return false;

        if (beta.Id == this.Id)
            return true;

        return base.Equals(obj);
    }

    public override int GetHashCode()
    {
        unchecked
        {
            int hash = 17;

            hash = hash * 23 + Id.GetHashCode();
            return hash;
        }
    }
}

映射:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Core" namespace="DataAccess.Models">
  <class name="BarDetail" table="BarDetail">
    <id name="Id">
      <generator class="identity"/>
    </id>
    <property name="IsEnabled" not-null="true"/>
    <many-to-one name="ParentFoo" class="Foo" column="FooId" not-null="true"/>
    <many-to-one name="alpha" class="Alpha" column="AlphaId" not-null="true"/>
    <many-to-one name="beta" class="Beta" column="BetaId" not-null="true"/>    
    <bag name="MonthlyDetailList" table="BarMonthlyDetail" lazy="true" cascade="save-update" order-by="Month asc" >
      <key>
        <column name="BarDetailId" not-null="true"/>
      </key>
      <one-to-many class="BarMonthlyDetail"/>
    </bag>
  </class>
</hibernate-mapping>

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Core" namespace="DataAccess.Models">
  <class name="BarMonthlyDetail" table="BarMonthlyDetail">
    <id name="Id">
      <generator class="identity"/>
    </id>
    <property name="Month" />
    <many-to-one name="ParentBarDetail" class="BarDetail" column="BarDetailId" not-null="true"/>
  </class>
</hibernate-mapping>

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Core" namespace="DataAccess.Models">
  <class name="Foo" table="Foo">

    <id name="Id">
      <generator class="identity"/>
    </id>

    <many-to-one name="bar" class="Bar" column="BarId" not-null="true"/>

    <bag name="BarDetailList" table="BarDetail" lazy="true" cascade="save-update">
      <key>
        <column name="FooId" not-null="true"/>
      </key>
      <one-to-many class="BarDetail"/>
    </bag>

  </class>
</hibernate-mapping>

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Core" namespace="DataAccess.Models">
  <class name="Beta" table="Beta">
    <id name="Id">
      <generator class="identity" />
    </id>
    <property name="IsEnabled" not-null="true"/>
    <many-to-one name="bar" class="Bar" column="BarId" not-null="true" />
    <many-to-one name="alpha" class="Alpha" column="AlphaId" not-null="true" />
  </class>
</hibernate-mapping>

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Core" namespace="DataAccess.Models">
  <class name="Alpha" table="Alpha">
    <id name="Id">
      <generator class="identity" />
    </id>
    <set name="alphas" table="AlphaBar" lazy="true">
      <key column="AlphaId" not-null="true"/>
      <many-to-many class="Bar" column="BarId"/>
    </set>
    <set name="betas" table="Beta" lazy="true" inverse="true">
      <key column="BarId" not-null="true"/>
      <one-to-many class="Beta" />
    </set>
  </class>
</hibernate-mapping>

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Core" namespace="DataAccess.Models">
  <class name="Bar" table="Bar">
    <id name="Id">
      <generator class="identity" />
    </id>
    <set name="Users" table="UserBar" inverse="true" lazy="true">
      <key column="BarId"/>
      <many-to-many class="UserAccount" column="UserId"/>
    </set>
    <set name="alphas" table="AlphaBar" inverse="true" lazy="true">
      <key column="BarId"/>
      <many-to-many class="Alpha" column="AlphaId"/>
    </set>
    <set name="betas" table="Beta" lazy="true" inverse="true">
      <key column="BarId" not-null="true"/>
      <one-to-many class="Bar" />
    </set>
  </class>
</hibernate-mapping>

我试图寻找类似的SO帖子(例如This )和或网络,但此问题似乎有所不同

更新:我也尝试通过显式设置冲洗模式session.FlushMode = FlushMode.Commit; 以前,它设置为“ Auto但错误仍然存​​在

我摆脱了错误。 当我将Set更改为Bag并仅基于Id GetHashCode()方法时,我正在使用它,它可以正常工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM