NHibernate SaveOrUpdate объединяет дочерние коллекции

У меня есть класс Journal, который имеет IList из JournalLine объекты.

Я создал Journal и случайно пропустил один и тот же метод генерации строк дважды. Начало вызова этого метода _journalLines.Clear() и конец делает _session.SaveOrUpdate(journal), Итак, у меня есть эта последовательность:

  1. генерировать Journal без линий звоните SaveOrUpdate, Все в порядке.
  2. Генерировать три JournalLines с идентификаторами 1,2,3, добавить в Journal._journalLines и позвонить SaveOrUpdate
  3. Вызов Journal._journalLines.Clear(), Точка останова после этого показывает, что список строк пуст.
  4. Генерировать три JournalLines с идентификаторами 4,5,6, добавить в Journal._journalLines и позвонить SaveOrUpdate, Точка останова здесь показывает _journalLines иметь три вещи в этом.
  5. Я остался с Journal это имеет 6 строк.

Все это происходит за одну транзакцию, и в базе данных ничего не сохраняется до ее завершения.

Почему это объединение двух коллекций? Мне кажется, что это должно дойти до последнего SaveOrUpdate где точка останова показывает, что у него есть три строки, и сохраните его как имеющий три строки. Остальные три остаются где-то в памяти, потому что еще не было флеша?

Изменить: отображение

public JournalMap()
{
    // Other stuff
    HasMany(x => x.JournalLines)
        .Access.CamelCaseField(Prefix.Underscore)
        .Cascade.AllDeleteOrphan();
}

public JournalLineMap()
{
    // Other stuff
    References(x => x.Journal);
} 

Journal имеет эти:

private readonly IList<JournalLine> _journalLines = new List<JournalLine>();
public virtual IEnumerable<JournalLine> JournalLines 
                                       { get { return _journalLines; } }

Фактический код, который генерирует строки, слишком сложен, чтобы добавить сюда, но он вызывает _journalLines.Add(journalLine); после генерации, а затем вызывает это, T будучи Journal

 public T Add(T entity)
 {
     _session.SaveOrUpdate(entity);
     return entity;
 }

Прежде чем в конце концов позвонить _session.Flush() а также _session.Transaction.Commit(); если сброс не ошибка

1 ответ

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

<bag name="JournalLines" lazy="true" inverse="true" cascade="save-update"
 ...

Тогда что происходит (используя похожие номера шагов):

  1. ...
  2. На данный момент коллекция содержит элементы 1,2,3 ... SaveOrUpdate(jurnal) будет делать каскад. Он также выполняет каскадирование, т.е. сеанс знает об этих трех элементах, которые необходимо сохранить.
  3. Clear() очистит IList<> но нет каскадного триггера для удаления этих элементов из сеанса. На данный момент наши первые 3 JournalLines действительно сироты. Никто не заботится о них
  4. ...
  5. Flush() при срабатывании транзакции все журнальные линии будут вставлены в БД

Решение: измените отображение на

cascade="all-delete-orphan"

ПРИМЕЧАНИЕ. Исходя из того, что вы указали выше, я думаю, что это сценарий (я только что объяснил). Другая проблема, с которой вы можете столкнуться, если вы позвоните session.SaveOrUpdate(eachJournalLine) , В таком случае Clear() недостаточно, вы также должны перебрать все удаленные элементы и установить их отношение к line.Journal = null

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