Удаление объектов во вложенных коллекциях - PullRequest
1 голос
/ 10 марта 2020

У меня проблема с сохранением изменений в базе данных при обновлении сущности, когда в методе сущности удалены несколько дочерних элементов коллекции. Я вызываю RemoveSpecificMiddleLvlEntities метод из HighLvlEntity сущности. Некоторые дети удалены. При обновлении методом Update из EfRepository выдается следующая ошибка. Должен ли я вручную обрабатывать все уровни дочерних элементов в моем методе удаления? Я думаю, что я действительно не понимаю одну из основ c концепций Entity Framework 6? Хотелось, чтобы у меня была логика c, какие сущности удаляются в моей сущности, а не в каком-либо репозитории или службе.

Заранее спасибо.

Ошибка: System.InvalidOperationException: "The операция не выполнена: отношение не может быть изменено, так как одно или несколько свойств внешнего ключа не могут иметь значение NULL. Когда в отношение вносится изменение, соответствующему свойству внешнего ключа устанавливается нулевое значение. ключ не поддерживает нулевые значения, должно быть определено новое отношение, свойству внешнего ключа должно быть назначено другое ненулевое значение или не связанный объект должен быть удален. "

Мои упрощенные объекты:

public class Base
{
    public Guid Id { get; set; }

    public Base()
    {
        Id = Guid.NewGuid();
    }
}
public class HighLvlEntity : Base
{
    public HighLvlEntity(string name)
    {
        Name = name;
    }
    public string Name { get; set; }
    public ICollection<MiddleLvlEntity> middleLvlEntities { get; set; } = new List<MiddleLvlEntity>();

    public void RemoveSpecificMiddleLvlEntities(ICollection<MiddleLvlEntity> middleLvlEntitiesOfCriteria)
    {
        foreach (var MiddleLvlEntity in middleLvlEntitiesOfCriteria)
        {
            var foundmiddleLvlEntity = middleLvlEntities.Where(p => p.Testcriteria == MiddleLvlEntity.Testcriteria).First();
            middleLvlEntities.Remove(foundmiddleLvlEntity);
            {
            }
        }
    }
}
public class MiddleLvlEntity : Base
{
    public MiddleLvlEntity(string testcriteria)
    {
        Testcriteria = testcriteria;
    }
    public ICollection<LowLvlTwo> LowLvlTwos { get; set; } = new List<LowLvlTwo>();
    public ICollection<LowLvlOne> LowLvlOnes { get; set; } = new List<LowLvlOne>();
    public string Testcriteria { get; set; }
    public HighLvlEntity HighLvlEntity { get; set; }
    public Guid HighlvlEntityId { get; set; }
}
public class LowLvlOne : Base
{
    public LowLvlOne(DateTime date)
    {
        Date = date;
    }
    public DateTime Date { get; set; }
    public Guid middleLvlEntityId { get; set; }
    public MiddleLvlEntity MiddleLvlEntity { get; set; }
}
public class LowLvlTwo : Base
{
    public LowLvlTwo(DateTime date)
    {
        Date = date;
    }
    public DateTime Date { get; set; }
    public Guid middleLvlEntityId { get; set; }
    public MiddleLvlEntity MiddleLvlEntity { get; set; }
}

EfRepository:

public class EfRepository<T> : IRepository<T> where T : Base
{
    protected readonly Context _dbContext;

    public EfRepository(Context dbContext)
    {
        _dbContext = dbContext;
    }

    public void Update(T entity)
    {
        _dbContext.Entry(entity).State = EntitieState.Modified;

        _dbContext.SaveChanges();
    }

    public void Delete(T entity)
    {
        _dbContext.Set<T>().Remove(entity);
        _dbContext.SaveChanges();
    }
}

Обновление: Это похоже на ту же проблему . Тогда мой вопрос: как, черт возьми, я могу спроектировать мое приложение, чтобы оно работало. У меня есть основной проект с сущностями, интерфейсами и сервисами. Инфраструктурный проект с внедрением и подключением к Entity Framework. Так что мои сущности в основном проекте не знают о dbcontext и удалении элементов из дочерних коллекций. Нужно ли переходить от идеи реализовать бизнес-логику c в самой сущности, чтобы использовать сервисные интерфейсы в базовом проекте и реализации сервисов в инфраструктурном проекте?

1 Ответ

0 голосов
/ 11 марта 2020

К сожалению, кажется, что с EF6 (в большинстве случаев) невозможно иметь полное невежество с сущностями, когда кто-то хочет правильно обрабатывать так называемые потерянные записи.

Как удалить дочерний элемент из много связанных записей в первой базе данных кода EF?

Итак, каковы альтернативы?

Укусите пулю и сделайте сущности осведомленными (минимально).

Очевидно не то, что вам нужно, но если мы

  1. переделаем наши сущности более DDD -подобным образом в виде больших агрегатов, ориентированных на операции / задачи вместо простых сущностей
  2. и разумно абстрактное постоянство

это может в конечном итоге не быть таким плохим, как могло бы выглядеть сейчас

Добавить некоторую умную пользовательскую обработку потерянных объектов в SaveChanges (или et c). )

Что-то вроде { ссылка }

Или попытайтесь извлечь максимум из идентифицирующих отношений - для них работает удаление сирот.

Не удалять права es

Если не существует требования (ограничение домена, размер / производительность БД, GDPR ...) для фактического удаления этих объектов, вы можете просто пометить их как удаленные или добавить к некоторым DeletedParent.

Хорошо, я понимаю, что это может быть неосуществимо, и это сделает некоторые аспекты системы более сложными и подверженными ошибкам, но во многих случаях не удаление сущностей может быть весьма выгодным (способность откатывать операции назад, создавать исторические данные). data and et c.)

Использование EF Core (2.2?)

EF Core поддерживает правильное удаление сирот .

И пока вы не сможете использовать EF Core 3.0 с. NET Framework, вы все еще можете попробовать EF Core 2.2, поскольку он также должен поддерживать удаление осиротевших.

Да, есть Есть некоторые различия между EF и EF Core, но для проекта, который, по-видимому, находится на ранних стадиях, они не являются непреодолимыми.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...