Tout en essayant de sauver un objet avec ses enfants, NHibernate jettetransaction NHibernate commit ou rollback pour un graphe d'objet lance « ObjectDisposedException »
System.ObjectDisposedException: 'Cannot access a disposed object.'
lorsque le tx.Commit()
est appelé.
Étrangement, les données sont toujours conservées dans les tables de base de données.
Ma session NHibernate est liée à la demande web via
if (!CurrentSessionContext.HasBind(sessionFactory))
CurrentSessionContext.Bind(sessionFactory.OpenSession());
J'utilise ASP.NET MVC 5, NHibernate 4.1, (Ne pas utiliser Fluent NHibernate bien)
est Ci-dessous le code qui produit l'erreur:
code:
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();
}
}
Définitions de classe:
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;
}
}
}
Mappages:
<?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>
j'ai essayé de chercher des semblables SO messages (par exemple This) et ou sur le Web, mais ce problème semble être différent
Mise à jour: J'ai aussi essayé en réglant le mode flush explicitement session.FlushMode = FlushMode.Commit;
précédemment, il a été mis à Auto
mais l'erreur persiste
Votre 'try catch' est inutile et même dangereux (exception swallow). Le 'using 'est suffisant. Si elle n'est pas validée, la transaction sera annulée. Vous cachez peut-être l'erreur réelle avec. Essayez à nouveau sans. –
Le code inutile est découpé dans le bloc 'catch'. Je fais de la journalisation et, dans certains cas, je convertis l'exception en une autre. J'ai mis à jour le bloc catch. –
Etes-vous sûr que votre 'ObjectDisposedException' ne provient pas de votre bloc catch? Vous n'avez pas inclus la trace de la pile, vous n'avez pas dit quelle ligne la lançait. –