NHibernate SaveOrUpdate объединяет дочерние коллекции
У меня есть класс Journal
, который имеет IList
из JournalLine
объекты.
Я создал Journal
и случайно пропустил один и тот же метод генерации строк дважды. Начало вызова этого метода _journalLines.Clear()
и конец делает _session.SaveOrUpdate(journal)
, Итак, у меня есть эта последовательность:
- генерировать
Journal
без линий звонитеSaveOrUpdate
, Все в порядке. - Генерировать три
JournalLines
с идентификаторами 1,2,3, добавить вJournal._journalLines
и позвонитьSaveOrUpdate
- Вызов
Journal._journalLines.Clear()
, Точка останова после этого показывает, что список строк пуст. - Генерировать три
JournalLines
с идентификаторами 4,5,6, добавить вJournal._journalLines
и позвонитьSaveOrUpdate
, Точка останова здесь показывает_journalLines
иметь три вещи в этом. - Я остался с
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,3 ...
SaveOrUpdate(jurnal)
будет делать каскад. Он также выполняет каскадирование, т.е. сеанс знает об этих трех элементах, которые необходимо сохранить. Clear()
очиститIList<>
но нет каскадного триггера для удаления этих элементов из сеанса. На данный момент наши первые 3 JournalLines действительно сироты. Никто не заботится о них- ...
Flush()
при срабатывании транзакции все журнальные линии будут вставлены в БД
Решение: измените отображение на
cascade="all-delete-orphan"
ПРИМЕЧАНИЕ. Исходя из того, что вы указали выше, я думаю, что это сценарий (я только что объяснил). Другая проблема, с которой вы можете столкнуться, если вы позвоните session.SaveOrUpdate(eachJournalLine)
, В таком случае Clear()
недостаточно, вы также должны перебрать все удаленные элементы и установить их отношение к line.Journal = null