繁体   English   中英

EF Core 中的软删除嵌套实体

[英]Soft delete nested entities in EF Core

我有一些嵌套实体,当我软删除该记录(如硬删除)时,我想自动软删除该记录的子项。 我怎样才能做到这一点? 最好的方法是什么?

class Base
{
    bool isDeleted { set; get; }
}

class A : Base
{
    //Collection of B
}

class B : Base
{
    //Collection of C
}

class C : Base
{
    //Collection of D
}
....

例如:

表 A:

    Id    ForeignKey(B Id)    isDeleted 
    -------------------------------------
    1        1                 false

表 B:

   Id    ForeignKey(C Id)    isDeleted
   -------------------------------------
    1        1                 false
    1        2                 false
    1        3                 false

表 C:

    Id    ForeignKey(D Id)    isDeleted
    -------------------------------------
    1        1                 false
    1        2                 false
    2        3                 false
    2        4                 false
    3        5                 false
    3        6                 false

代码:

public void SoftDeleteA()
{
     //A.isDeleted = true;
     //???How to soft-delete related records in B,C,D ,...
     //SaveChanges();
}

现在当我从 A 软删除行时,B 和 C 的所有行也必须被软删除

实体框架没有自动的方法来实现这一点。 软删除只是一个术语,它实际上并没有删除记录,而只是更新单个列值,因此不会影响相关实体。 但是,您可以使用实体框架或 SQL 触发器来执行此操作。 由于您希望这自动发生,请在表 A 上创建一个更新触发器,并在更新记录的相关表中设置 isDeleted。

触发相关文章:
https://docs.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql?view=sql-server-ver15
https://www.tutorialgateway.org/after-update-triggers-in-sql-server/
https://www.sqlshack.com/triggers-in-sql-server/
https://www.aspsnippets.com/Articles/Simple-Insert-Update-and-Delete-Triggers-in-SQL-Server-with-example.aspx

使用实体框架,您需要首先获取您的父级和所有子级,单独修改它们并保存到数据库。

例子:

public A FetchA()
{
  return _context.A
          .Include(a=>a.CollectionB)
          .ThenInclude(b=>b.CollectionC)
          .FirstOrDefaultAsync();
}

public void SoftDeleteA()
{
    var a = FetchA();
    if(a !=null)
    {
       a.isDeleted = true;

       // loop through all related records and update them
       if(a.CollectionB?.Any()== true)
       { 
           foreach(var itemB in a.CollectionB)
           {
               itemB.isDeleted = true;

               // loop through all related records and update them
               if(itemB.CollectionC?.Any()== true)
               { 
                   foreach(var itemC in itemB.CollectionC)
                   {
                       itemC.isDeleted = true;
                   }         
               }
           }
       }

       // save changes at last
       _context.Update(a);
       await _context.SaveChangesAsync() ;
    }

}

或者,如果您可以选择使用 SQL,只需运行原始 sql,这比使用 EF 快得多。

例子:

update b
set isDeleted = a.isDeleted
from B b
inner join A a on b.ID = a.ID

我正在使用类似Recursive Functions的东西;

class Base
{
      public virtual bool IsDeleted { get; set; }
      public virtual void DeleteMethod(int modifiedBy)
      {
          IsDeleted = true;
          ModifiedMethod(modifiedBy);
      }
}

class A : Base
{
    //Collection of B
    
    public override void DeleteMethod(int modifiedBy)
    {
        B.ForEach(oe => oe.DeleteMethod(modifiedBy));
        base.DeleteMethod(modifiedBy);
    }
}

class B : Base
{
    //Collection of C
    
    public override void DeleteMethod(int modifiedBy)
    {
        C.ForEach(oe => oe.DeleteMethod(modifiedBy));
        base.DeleteMethod(modifiedBy);
    }
}

class C : Base
{
    //Collection of D
    
    public override void DeleteMethod(int modifiedBy)
    {
        D.ForEach(oe => oe.DeleteMethod(modifiedBy));
        base.DeleteMethod(modifiedBy);
    }
}

当调用一些{ParentClass}.DeleteMethod()时,它开始对子类进行操作。 上面的答案相同,但涵盖了所有继承的类,不需要每个方法再次编写循环。

public async Task SoftDeleteAsync()
{
    ..
    A.DeleteMethod(userid);
    await context.SaveChangesAsync();
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM