【问题标题】:How to cascade an update in a one to many relationship in ef-core如何在 ef-core 中以一对多关系级联更新
【发布时间】:2020-01-31 18:29:40
【问题描述】:

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

【问题讨论】:

    标签: asp.net-core ef-core-3.0


    【解决方案1】:

    您可以在 DbContext 中重写 SaveChangesAsync 方法以更新父实体和子实体中的 isDeleted 值。另外,请记住禁用 EF 核心的级联删除行为。

    参考以下步骤:

    1.型号:

    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.删除动作

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

    【讨论】:

    • @hrz 很高兴您解决了问题。您现在可以接受我的回答吗?
    猜你喜欢
    • 2021-07-13
    • 1970-01-01
    • 2019-11-11
    • 2017-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-11
    • 1970-01-01
    相关资源
    最近更新 更多