Удаление и добавление дочерних объектов в одной транзакции сбивает с толку nhibernate
Я получаю классическую ошибку:
'deleted object would be re-saved by cascade
(remove deleted object from associations)[DrillingContracts.Domain.TrackedField#3216'
Но с добавленным поворотом, ошибка возникает полностью, потому что я удаляю одну сущность и добавляю новую.
Я очищаю всех ранее существующих детей с помощью этого метода
public void RemoveChildren(TrackedNode parentNode)
{
foreach (TrackedField trackedField in parentNode.ChildNodes)
{
_trackedFieldRepository.Delete(trackedField);
parentNode.RemoveChildNode(trackedField);
}
}
Затем добавьте новые сразу
public virtual void AddTrackedChildFieldsToTrackedCell(
params TrackedField[] nodes)
{
foreach (var field in nodes)
{
if (IsPath(field.Name))
{
throw new InvalidTrackedFieldNameException(
"The value " + field.Name + " is not a valid tracked field name.");
}
field.Supplement = this;
_trackedFields.Add(field);
}
}
Для тех из вас, кто хочет знать, что происходит в хранилище, лучший ответ у меня есть магия. 10000% магии. Первоначальный разработчик использовал NCommon. Оба эти метода вызываются из метода, заключенного в атрибут NCommon.UnitOfWork.
Следует отметить, что каждый метод работает, как и ожидалось, сам по себе. (То есть, нет полей, чтобы удалить добавление работает, и аналогично, нет полей, чтобы добавить удаление работает.)
РЕДАКТИРОВАТЬ
[HttpPost]
[UnitOfWork(Scope = FilterScope.Result)]
public ActionResult SaveEditMode(long id, AddTrackedRowViewModel model, string editMode, List<string> elementNames, string provisionData)
{
var supplement = _supplementCoordinator.GetSupplement(id);
var table = supplement.TrackedTables.First(x => x.Name == model.Name);
var valueAttributes = JsonSerializer.DeserializeFromString<List<ValueAttributeViewModel>>(provisionData);
foreach (var prop in valueAttributes)
{
supplement.Set(prop.Attribute, prop.Value, false);
}
var cell = table.TrackedRows.First(x => x.Ordinal == model.Ordinal).TrackedCells.First(x => x.Name == "Detail");
_supplementCoordinator.RemoveChildren(cell);
if (elementNames != null)
{
var childNodes = elementNames.Select((t, i) => new TrackedField(cell, t, i)).ToList();
supplement.AddTrackedChildFieldsToTrackedCell(childNodes.ToArray());
}
return SwitchEditMode(model, editMode, table);
}
Ответ
public void AddChildren(Supplement supplement, TrackedNode parentNode, params TrackedField[] nodes)
{
foreach (TrackedField trackedField in nodes)
{
parentNode.AddChildNode(trackedField);
}
supplement.AddTrackedChildFieldsToTrackedCell();
}
Я не получал их как новые права на родительский узел, только связанное дополнение.
1 ответ
Просто для полноты. Сообщение "удаленный объект будет повторно сохранен.." было вызвано явным вызовом session.Delete(instance)
,
В этом случае нам нужно только 1) удалить такой элемент из старой родительской коллекции и 2) добавить его к новому родителю. Каскадное отображение и session.Flush() будут корректно обновлять БД.
Последнее замечание: такое "движение" должно быть сделано внутри одной сессии / транзакции, чтобы избежать других проблем (например, "Строка была обновлена или удалена другой транзакцией...").