2010-03-04 5 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: удаленный объект будет повторно сохранен каскадом (удалить удаленный объект из ассоциаций)

Я гугл этой ошибки , и нашел ряд статей об этом, но ничего не предлагалось, кажется, работает. Я добавил «.Inverse()» в родительском сопоставлении. Я попытался изменить каскадное из «All» в «SaveUpdate» (он никогда не был установлен в «AllDeleteOrphans», который некоторые сообщения упоминались как проблема.) Я очищаю все репозитории, и я попробовал обернуть все это в сделка. Я попытался добавить флеш после Session.Delete. Сначала я попытался очистить родительский репозиторий, а потом - ребенка. Ничто не избавляется от ошибки.

Любая помощь будет оценена по достоинству.

ответ

0

Вы не показываете его в своих сопоставлениях, но предположительно Узел имеет ссылку на его родительский контракт. Чтобы удалить подразделение, вы должны установить ссылку на контракт на нуль и, в зависимости от вашего сопоставления, удалить его из коллекции единиц контракта.

+0

Jamie, В таблице POCO или в файле HBM.XML нет ссылки на таблицу контракта. Созданная схема включает столбец Contract_Id в таблице Unit, который, как я понимаю, происходит из элемента bag/key/column name = "Contract_Id" в файле контракта HBM.XML. Но если бы были, что, если я просто хочу очистить все таблицы? I.e., выполните эквивалент «УДАЛИТЬ ОТ единиц» и «УДАЛИТЬ ИЗ КОНТЕНТОВ». Должен ли я проходить через каждый элемент цикла for и удалять каждый элемент? –

+0

Эта ошибка обычно возникает, когда вы удаляете объект, на который все еще ссылается другой объект. Когда ISession сбрасывается, ссылка заставляет повторно удалить удаленный объект. Поскольку у вас есть cascade = all, этого должно быть достаточно, чтобы удалить Контракты, и это приведет к удалению всех единиц. –

+0

Я проверю его, когда вернусь к работе в понедельник, но я уверен, что сначала попытался вызвать Clear на ContractsRepository, и у меня все еще была та же ошибка. –

Смежные вопросы