Удаление и добавление дочерних объектов в одной транзакции сбивает с толку 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() будут корректно обновлять БД.

Последнее замечание: такое "движение" должно быть сделано внутри одной сессии / транзакции, чтобы избежать других проблем (например, "Строка была обновлена ​​или удалена другой транзакцией...").

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