如何在 ef-core 的一对多关系中级联更新

How to cascade an update in a one to many relationship in ef-core

我有从Api申请人table到Apitable的多对一关系。我的 Api table 有以下字段: Api: ID, name, date, isDeleted ApiAppliant:Id,ApiID,ApplicantId,ApiRequestDate,gateId,isDeleted。 ApiId 是 ApiApplicant to Api table 中的外键。现在我的问题是,如果用户想删除一条 Api 记录,只有相关的 isDeleted 值应该更改为 1。然后在 ApiApplicant table 中,具有相同的 ApiId,isDeleted 值也应为 1。我是 ef-core 和 asp.net 的新手。如果有人通过显示示例代码向我提出解决方案,我将不胜感激。

您可以重写 DbContext 中的 SaveChangesAsync 方法以更新父实体和子实体中的 isDeleted 值 entities.Also,记得禁用 EF 核心的级联删除行为。

参考以下步骤:

1.Models:

public class Api
{
    [Key]
    public int ID { get; set; }

    //other properties

    public bool isDeleted { get; set; }
    public List<ApiApplicant> ApiApplicants { get; set; }
}

public class ApiApplicant
{
    [Key]
    public int Id { get; set; }
    public int? ApiID { get; set; }//set as nullable

    //other properties

    public bool isDeleted { get; set; }
    [ForeignKey("ApiID")]
    public Api Api { get; set; }
}

2.DbContext(禁用默认级联删除)

public class ApplicationDbContext : IdentityDbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }

    public DbSet<Api> Apis { get; set; }
    public DbSet<ApiApplicant> ApiApplicants { get; set; }


    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {

        modelBuilder.Entity<Api>()
                    .HasMany(i => i.ApiApplicants)
                    .WithOne(c => c.Api)
                    .OnDelete(DeleteBehavior.Restrict);
    }

    public override int SaveChanges(bool acceptAllChangesOnSuccess)
    {
        OnBeforeSaving();
        return base.SaveChanges(acceptAllChangesOnSuccess);
    }

    public override Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default(CancellationToken))
    {
        OnBeforeSaving();
        return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
    }

    private void OnBeforeSaving()
    {


        foreach (var entry in ChangeTracker.Entries())
        {
            if (entry.State == EntityState.Deleted)
            {
                if (entry.Entity is Api )
                {
                    entry.State = EntityState.Modified;
                    //change Api.isDeleted value to true
                    entry.CurrentValues["isDeleted"] = true;

                    //change navigations' isDeleted value to true
                    foreach (var c in entry.Collections)
                    {
                        if(c.Metadata.Name == "ApiApplicants")
                        {
                            foreach (var item in (IEnumerable)c.CurrentValue)
                            {
                                    ((ApiApplicant)item).isDeleted = true;
                            }
                        }

                    }

                }
            }
        }
    }
}

3.Delete 动作

[HttpPost]
public async Task<IActionResult> DeleteConfirmed(int id)
    {
        var api = await _context.Apis.Include(a => a.ApiApplicants).FirstOrDefaultAsync(a=>a.ID == id);
        _context.Apis.Remove(api);
        await _context.SaveChangesAsync();
        return RedirectToAction(nameof(Index));
    }