对象图的NHibernate事务提交或回滚抛出'ObjectDisposedException'

时间:2017-06-29 05:28:00

标签: c# asp.net asp.net-mvc nhibernate transactions

在尝试将对象与其子节点一起保存时,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)和/或web但这个问题似乎有所不同

更新:我之前尝试过显式设置刷新模式session.FlushMode = FlushMode.Commit;,它已设置为Auto但错误仍然存​​在

1 个答案:

答案 0 :(得分:0)

我摆脱了错误。当我将<ul class="vc_tta-tabs-list"> <li class="vc_tta-tab"> <a href="#ID-element-1">Tab 1</a> </li> <li class="vc_tta-tab"> <a href="#ID-element-2">Tab 2</a> </li> <li class="vc_tta-tab"> <a href="#ID-element-3">Tab 3</a> </li> <li class="vc_tta-tab"> <a href="#ID-element-4">Tab 4</a> </li> </ul> <div class="vc_tta-panel" id="ID-element-1">SOME TEXT 1</div> <div class="vc_tta-panel" id="ID-element-2">SOME TEXT 2</div> <div class="vc_tta-panel" id="ID-element-3">SOME TEXT 3</div> <div class="vc_tta-panel" id="ID-element-4">SOME TEXT 4</div>更改为Set并仅在Bag上使用GetHashCode()方法时,我使用了Id,它开始正常工作。