Исключение при удалении дочерних записей в 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 с AutoMapping. Вот мой класс AutoMapping:

   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, которые генерирует Fluent:

(для таблицы Units):

<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. Я попытался сначала очистить родительский репозиторий, а затем ребенка. Ничто не избавляет от ошибки.

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

1 ответ

Решение

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

Другие вопросы по тегам