删除嵌套集合中的条目

Deleting entites in nested collections

在实体方法中删除了多个 children 集合的更新实体时,我无法将更改保存到数据库。 我从 HighLvlEntity 实体调用 RemoveSpecificMiddleLvlEntities 方法。一些 Children 被删除。当通过 EfRepository 的 Update 方法进行更新时,抛出以下错误。 我是否必须通过我的 Delete 方法手动删除集合中所有级别的 children? 我想我并没有真正理解 Entity Framework 6 个基本概念之一?想让我的逻辑在我的实体中删除哪些实体,而不是在任何存储库或服务中。

提前致谢。

Error: System.InvalidOperationException: "The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted."

我的简化实体:

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();
    }
}

更新: This seems to be same problem。 那么我的问题是,我到底如何构建我的应用程序才能正常工作。我有一个包含实体、接口和服务的核心项目。实施并连接到 Entity Framework 的基础设施项目。所以我在核心项目中的实体不知道 dbcontext 和从子集合中删除项目。我是否必须从在实体本身中实现业务逻辑的想法转变为在基础设施项目中的核心项目和服务实现中使用 service-interfaces?

不幸的是,当人们想要正确处理所谓的孤立记录时,使用 EF6 似乎(大部分)不可能对实体具有完全的持久​​性无知。

How to remove child one to many related records in EF code first database?

那么,有哪些替代方案?

硬着头皮让实体持久化感知(最低限度)。

显然不是你想要的,但如果我们

  1. 以更 DDD 的方式重塑我们的实体作为更大的 operation/task-oriented 聚合而不是普通实体
  2. 和明智的抽象持久性

它最终可能不会像现在看起来那么糟糕

在 SaveChanges(或其他)上添加一些巧妙的自定义孤儿处理

类似

或者尝试从 identifying relationships 中获得最大收益 - 对他们来说,孤儿删除是可行的。

不删除实体

除非有要求(域限制、DB size/performance、GDPR...)实际删除这些实体,否则您可以将它们标记为已删除或将它们添加到某些 DeletedParent

好吧,我知道这可能不可行,它会使系统的某些方面更加复杂和容易出错,但在许多情况下,不删除实体可能是非常有利的(能够回滚操作,产生历史数据等)

使用 EF Core (2.2?)

EF Core 似乎支持正确的 orphan removal

虽然您无法 使用 .NET Framework,但您仍然可以尝试 EF Core 2.2,因为它也应该支持孤立删除。

是的,EF 和 EF Core 之间存在一些差异,但对于一个看似处于早期阶段的项目来说,它们并非无法克服。