【问题标题】:How to delete child automatically based on parent deletion for database first approach (.edmx)? [duplicate]如何根据数据库优先方法(.edmx)的父删除自动删除子? [复制]
【发布时间】:2017-09-27 14:49:01
【问题描述】:

以下是我的 2 个班级分享一对多的关系:

public partial class Employee
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Skills> Skills { get; set; }
}

public partial class Skills
{
    public int Id { get; set; }
    public Nullable<int> EmployeeId { get; set; }
    public string Skills { get; set; }
    public virtual Employee Employee { get; set; }
}

现在我正在尝试通过以下方式删除具有相应技能的员工:

1) 用一种方法删除员工和技能,只保存更改。我想在这种情况下我将获得性能优势,因为我只需要调用一次保存更改,但还有一个问题是,如果技能被删除,但如果在这种情况下删除员工时发生错误,我会失去对应员工的技能。

public void Delete(int[] ids)
{
    using (var context = new MyEntities())
    {
        context.Skills.RemoveRange(context.Skills.Where(cd => ids.Contains(cd.EmployeeId)));
        context.Employee.RemoveRange(context.Employee.Where(t => ids.Contains(t.Id)));
        context.SaveChanges();
    }
}

2) 另一种选择是使用事务来确保成功删除和孩子,如下所示:

public HttpResponseMessage Delete(int[] ids)
{ 
    using (var context = new MyEntities())
    {
        using (var transaction = context.Database.BeginTransaction())
        {
            try
            { 
                DeleteSkills(ids,context);
                DeleteEmployees(ids,context);
                transaction.Commit();
            }
            catch (Exception ex)
            {
                transaction.Rollback();
                // throw exception.
            }
        }
    }
}

public void DeleteEmployees(int[] ids,MyEntities _context)
{
    _context.Employee.RemoveRange(_context.Employee.Where(t => ids.Contains(t.Id)));
    _context.SaveChanges();
}

public void DeleteSkills(int[] ids, MyEntities _context)
{
    _context.Skills.RemoveRange(_context.Skills.Where(cd => ids.Contains(cd.EmployeeId)));
    _context.SaveChanges();
}

3) 我正在寻找一个选项,我不需要显式删除子(技能),并且子会根据父(员工)实体的删除自动删除,就像代码优先级联时发生的方式一样删除,这样我就不必触发 2 个查询来删除父项和子项(我的第一个选项),或者我不必维护事务(我的第二个选项。)

我做了一些研究,但在 数据库优先方法 (.edmx) 的情况下,无法根据删除父级自动删除子级的任何帮助。

什么是处理这种情况的有效方法?

【问题讨论】:

  • 相信DbContext.SaveChanges本身是使用事务的,所以不用担心case 1的部分删除
  • 为什么不使用这样的 SQL Cascade 删除行为 stackoverflow.com/a/37459049/2946329
  • 嗨学习。我注意到您的帖子存在许多问题,可以通过一些小的更改来避免这些问题。请您回答这些问题好吗? (1) 提及自己时,请始终使用大写的“I”。以英语为母语的读者通常会觉得读“i”很烦人,而这种轻微的挫败感会妨碍提供帮助。 (2) wasn't, could't, don't, doesn't 等词的最后一个字母前都有撇号。您是否可以在键入时添加它,或者在您的计算机上启用自动更正?
  • (3) 您的每个问题都附有“谁能帮助我?”这个问题。当然,答案通常只是“是”,但这不是您要寻求的回应。文章Why is “Can someone help me?” not an actual question? 在这里很有帮助。如果您可以将该短语与更具体的问题交换,那就太好了,否则请不要使用它。谢谢!
  • 为什么重新提出这个问题?我认为提议的副本是正确的。如果不是,那this one 呢?关键部分是数据库中的 FK 应该指定了级联删除。

标签: c# entity-framework edmx ef-database-first


【解决方案1】:

如果删除了一个或另一个实体,EF 会自动删除多对多关系实体的中间表中的相关记录。

因此,EF 默认为所有实体启用级联删除效果。

如果你想手动处理你可以使用:

 .WillCascadeOnDelete(false);


 protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<parent>()
            .HasOptional<child>(c => c.child)
            .WithMany()
            .WillCascadeOnDelete(false);
    }

【讨论】:

    【解决方案2】:

    了解实体框架中的删除行为。

    您可以选择实体在删除时的行为方式,以便影响子/依赖。

    在您的情况下,您需要“级联”删除行为,它会自动删除您要删除的实体的子项/依赖项。

    在你的 OnModelCreating 方法中这样做:

     protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<PARENT>()
                 .........
                .OnDelete(DeleteBehavior.Cascade);
        }
    

    看看这里如何使用和是什么:

    https://entityframeworkcore.com/saving-data-cascade-delete#:~:text=Entity%20Framework%20Core%20Cascade%20Delete&text=Cascade%20delete%20allows%20the%20deletion,delete%20behaviors%20of%20individual%20relationships.

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-26
      • 2016-02-20
      • 2017-05-26
      • 1970-01-01
      • 1970-01-01
      • 2022-01-22
      相关资源
      最近更新 更多