简体   繁体   English

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

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

After researching cascade deletes and browsing issues here, I'm under the impression that the following scenario will work 在研究了级联删除并在此处浏览问题之后,我认为以下情况将起作用

Entity with many: 有很多实体:

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

Entity with one: 具有一个的实体:

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

The foreign key on analysis entity is nullable, so that cascade deletion will automagically set the FK to null when it tries to delete the master record. analysis实体上的外键可以为空,因此,当级联删除尝试删除master记录时,它将自动将FK设置为​​null。

That configuration is in my Context : 该配置在我的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);
        }
    }

Then when I attempt to delete a master record by passing the id into the following (generic repo snippet, this works fine when deleting a master record with no analyses): 然后,当我尝试通过将id传递给以下内容来删除master记录时(通用存储库代码段,当删除不带分析的master记录时,此方法可以正常工作):

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

I get an error 我得到一个错误

Cannot delete or update a parent row: a foreign key constraint fails 无法删除或更新父行:外键约束失败

on this record. 在这个记录上。 What am I missing here? 我在这里想念什么?

The use of CascaseOnDelete should mirror cascade rules on the database. 使用CascaseOnDelete应该在数据库上镜像级联规则。 With CodeFirst when you set a relationship as Required, EF maps this both in the mapping and the schema as a delete cascade. 使用CodeFirst将关系设置为“必需”时,EF会在映射和架构中将其映射为删除级联。 With Optional relationships this isn't the case, it assumes deleting a parent will leave the child orphaned since the child accepts an existence without a parent due to it's null-able FK. 在使用可选关系的情况下,情况并非如此,它假定删除父级将使子级变为孤儿,因为子级由于其可空值而接受没有父级的存在。 However, without knowledge of the child records it cannot clear the ID out of the FK or delete the data so it relies on whatever the DB is set up to do. 但是,在不了解子记录的情况下,它无法从FK中清除ID或删除数据,因此它依赖于DB设置要执行的操作。

You can still use .WillCascadeOnDelete(), though for it to work, the context needs to know about the children. 您仍然可以使用.WillCascadeOnDelete(),尽管要使它起作用,上下文需要了解有关子项的信息。 For instance, on a new context: 例如,在新的上下文中:

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

This typically fails with a FK constraint error. 这通常会因FK约束错误而失败。 (SQL Server) The error message differs from yours so I suspect like Tetsuya that is a different provider? (SQL Server)错误消息与您的消息不同,因此我怀疑像Tetsuya那样的提供商是不同的吗?

To resolve this you can use: 要解决此问题,您可以使用:

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

though that can be tedious for objects with larger graphs to include all children. 尽管这对于具有较大图形的对象包含所有子项可能是乏味的。

As a general rule if you want to use cascade deletes, you need to ensure that the database schema is set up with a cascade on delete behaviour. 作为一般规则,如果要使用级联删除,则需要确保在删除行为上使用级联来设置数据库模式。 With a null-able FK and a cascade delete rule the original code should behave as expected. 使用可为空的FK和级联删除规则,原始代码应按预期运行。 Alternatively, Setting a cascade rule to "Set to Null" will leave the child records orphaned with a null FK. 或者,将级联规则设置为“设置为空”将使子记录变为空FK。 (no error from EF) (EF没有错误)

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

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