繁体   English   中英

如何配置Entity Framework级联删除以正确处理一对多关系?

[英]How do I configure Entity Framework cascade delete to work properly with a one to many relationship?

在研究了级联删除并在此处浏览问题之后,我认为以下情况将起作用

有很多实体:

public partial class master
{
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
        public master()
        {
            analysis = new HashSet<analysis>();
        }

        [Key]
        public int id { get; set; }

        [StringLength(50)]
        public string description { get; set; }

        public virtual ICollection<analysis> analysis { get; set; }
}

具有一个的实体:

public partial class analysis
{
        [Key]
        public int id { get; set; }

        [StringLength(50)]
        public string description { get; set; }

        public int? master_id { get; set; }

        public virtual master master { get; set; }
}

analysis实体上的外键可以为空,因此,当级联删除尝试删除master记录时,它将自动将FK设置为​​null。

该配置在我的Context

public class Context : DbContext
    {
        public Context() : base("Context")
        {
            this.Configuration.LazyLoadingEnabled = true;
            Database.SetInitializer(new DropCreateDatabaseIfModelChanges<Context>());
        }

        public virtual DbSet<master> master { get; set; }
        public virtual DbSet<analysis> analysis { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<master>()
                .HasMany(e => e.analysis)
                .WithOptional(e => e.master)
                .HasForeignKey(e => e.master_id)
                .WillCascadeOnDelete(true);
        }
    }

然后,当我尝试通过将id传递给以下内容来删除master记录时(通用存储库代码段,当删除不带分析的master记录时,此方法可以正常工作):

public void Delete(int id)
{
        var entity = FindByKey(id);
        _dbSet.Remove(entity);
        _context.SaveChanges();
}

我得到一个错误

无法删除或更新父行:外键约束失败

在这个记录上。 我在这里想念什么?

使用CascaseOnDelete应该在数据库上镜像级联规则。 使用CodeFirst将关系设置为“必需”时,EF会在映射和架构中将其映射为删除级联。 在使用可选关系的情况下,情况并非如此,它假定删除父级将使子级变为孤儿,因为子级由于其可空值而接受没有父级的存在。 但是,在不了解子记录的情况下,它无法从FK中清除ID或删除数据,因此它依赖于DB设置要执行的操作。

您仍然可以使用.WillCascadeOnDelete(),尽管要使它起作用,上下文需要了解有关子项的信息。 例如,在新的上下文中:

var master = _db.Masters.Find(id);
_db.Masters.Remove(master);

这通常会因FK约束错误而失败。 (SQL Server)错误消息与您的消息不同,因此我怀疑像Tetsuya那样的提供商是不同的吗?

要解决此问题,您可以使用:

var master = _db.Masters.Include(x=>x.analysis).Find(id);
_db.Masters.Remove(master);

尽管这对于具有较大图形的对象包含所有子项可能是乏味的。

作为一般规则,如果要使用级联删除,则需要确保在删除行为上使用级联来设置数据库模式。 使用可为空的FK和级联删除规则,原始代码应按预期运行。 或者,将级联规则设置为“设置为空”将使子记录变为空FK。 (EF没有错误)

暂无
暂无

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

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