2010-03-04 72 views
0

我有一个简单的父/子表。合同是父表。每份合同可以有多个单位。异常删除NHibernate中的子记录

这里是我的C#类定义(简体):

public class Contract : EntityWithIntID 
{ 
    public virtual string ContractNum { get; set; } 
    public virtual IList<Unit> Units { get; protected set; } 
    public virtual int NumberOfUnits 
    { 
     get { return Units.Count; } 
    } 
} 

    public class Unit : EntityWithIntID 
{ 
    <various Unit physical data fields> 
} 

我使用FluentNHibernate与自动映射。这里是我的自动映射类:

public static AutoPersistenceModel GetMappings() 
    { 
     AutoPersistenceModel returnModel = AutoMap.AssemblyOf<Contract>() 
      .IgnoreBase(typeof(EntityWithIntID)) 
      .Where(type => type.BaseType == typeof(EntityWithIntID)) 
      .Conventions.Add(typeof(PluralTableNamesConvention)) 
      .Conventions.Add(typeof(CascadeAllConvention)) 
      .Override<Contract>(map =>map.HasMany(cont =>cont.Units).Inverse()) 
      .Override<Contract>(map=>map.Map(cont => cont.ContractNum).Not.Nullable().Unique()) 
     ; 
     return returnModel; 
    } 
} 

下面是流利的生成hbm.xml文件:

(为单位表):

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-access="property" auto-import="true" default-cascade="none" default-lazy="true"> 
<class xmlns="urn:nhibernate-mapping-2.2" name="InterfaceDB.Unit, InterfaceDB, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="Units"> 
    <id name="Id" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> 
     <column name="Id" /> 
     <generator class="hilo"> 
     <param name="max_lo">10</param> 
     </generator> 
    </id> 
<!-- physical data property elements removed for brevity --> 
    </class> 
</hibernate-mapping> 

(和合同表):

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-access="property" auto-import="true" default-cascade="none" default-lazy="true"> 
    <class xmlns="urn:nhibernate-mapping-2.2" name="InterfaceDB.Contract, InterfaceDB, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="Contracts"> 
    <id name="Id" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> 
     <column name="Id" /> 
     <generator class="hilo"> 
     <param name="max_lo">10</param> 
     </generator> 
    </id> 
    <property name="ContractNum" type="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> 
     <column name="ContractNum" not-null="true" unique="true" /> 
    </property> 
    <bag cascade="all" inverse="true" name="Units"> 
     <key> 
     <column name="Contract_id" /> 
     </key> 
     <one-to-many class="InterfaceDB.Unit, InterfaceDB, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> 
    </bag> 
    </class> 
</hibernate-mapping> 

对于我的单元测试目的,我在每个存储库中都有一个“Clear()”方法,所以我可以从一个已知的空数据库。它只是一个

Session.Delete("from Unit"); 

后面跟着一个Debug.Assert(Repository.GetCount()== 0);

我的问题是,当我做了UnitsRepository.Clear(),我得到一个NHibernate.ObjectDeleteException:删除的对象将通过级联(移除协会删除的对象)

我用Google搜索的错误重新保存,并发现了一些关于它的文章,但没有任何建议似乎工作。我在父映射中添加了“.Inverse()”。我尝试将级联从“全部”更改为“保存更新”(从未设置为“AllDeleteOrphans”,某些帖子引用为问题)。我正在清除所有存储库,并且试图将整个事件包装在交易。我试着在Session.Delete后添加一个flush。我试着先清理父库,然后是孩子。没有什么摆脱错误。

任何帮助,将不胜感激。

回答

0

您不会在您的映射中显示它,但大概Unit会参考其父合同。为了删除单位,您必须将对合同的引用设置为空,并根据您的映射将其从合同的单位集合中删除。

+0

Jamie, 单位POCO或HBM.XML文件中没有对合同表的引用。创建的模式在Unit表中包含一个Contract_Id列,我认为它来自Contract HBM.XML文件中的bag/key/column name =“Contract_Id”元素。 但是,如果有,如果我只是想清除所有的表?即,做相当于“从单位删除”和“从合同中删除”。我是否必须遍历for循环中的每个元素并删除每个元素? –

+0

当您删除仍由其他对象引用的对象时,通常会发生该错误。当刷新ISession时,引用会导致删除的对象被重新保存。既然你有级联=全部它应该足以删除合同,这将删除所有的单位。 –

+0

我会在星期一回去工作时验证它,但我非常确定我首先尝试在ContractsRepository上调用Clear,并且仍然有同样的错误。 –