美文网首页Asp.net core mvc
EF Core级联删除的设定

EF Core级联删除的设定

作者: firechun | 来源:发表于2019-01-21 14:13 被阅读1次

    EF6和EF Core都支持级联删除。EF6要禁止级联删除是在数据库上下文的OnModelCreating方法中设置:

            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                //移除外键级联删除
                modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
                modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();
            }
    

    这个设置是对整个数据库的所有表起作用。

    EF Core禁止级联删除只能对表的每一个外键进行设定(反正我在EF Core文档中没找到对整个数据库设置的方法)。

    EF Core对删除父实体时可以执行三种操作:
    1. 可以删除子项/依赖项
    2. 子项的外键值可以设置为 null
    3. 子项保持不变
    第一种就是级联删除,即删除父项时自动删除相关的子项。
    第二种是删除父项时,将子项对应的外键值设置为null,如果该字段不能为null,则抛出异常。
    第三种就是约束了,因为删除父项而子项保持不变,这是违反数据库约束的,如果父项已经被引用,直接抛出异常。

    这三种操作被定义为枚举DeleteBehavior中的四个枚举值:

    行为名称 对内存中的依赖项/子项的影响 对数据库中的依赖项/子项的影响
    Cascade 删除实体 删除实体
    ClientSetNull 外键属性设置为 null
    SetNull 外键属性设置为 null 外键属性设置为 null
    Restrict

    对内存中的影响是指加载到内存中的数据,对数据库的影响则是在调用了SaveChange()方法后产生。可以看到ClientSetNull和Restrict对数据库的影响是一样的,所以说四个枚举值,实际上只有三种操作。

    EF Core在创建数据库时,会根据外键是否允许为null来设置删除行为。

    如果外键不允许为null,删除行为设置为Cascade,此时删除父项会自动删除相关的所有子项。当调用SaveChange()方法时,这一规则也会同样应用到数据库。

    如果外键允许为null,删除行为设置为ClientSetNull,对应到数据库就是Restrict,删除被引用的父项时,如果没有调用SaveChange()方法,不会有任何问题,但调用SaveChange()时会抛出异常。

    在代码中设定删除行为,可以重写数据库上下文的OnModelCreating方法:

            protected override void OnModelCreating(ModelBuilder builder)
            {
                base.OnModelCreating(builder);
                //表只有一个外键
                builder.Entity<Project>()
                    .HasOne(p => p.Agent)
                    .WithMany()
                    .OnDelete(DeleteBehavior.Restrict);
                //表有多个外键
                builder.Entity<Light>(b =>
                {
                    b.HasOne(l => l.LedController).WithMany().OnDelete(DeleteBehavior.Restrict);
                    b.HasOne(l => l.ControllerArea).WithMany().OnDelete(DeleteBehavior.Restrict);
                });
            }
    

    HasOne方法的参数指向表的主表,比如上面的代码中,Agent是主表,Project是子表。WithMany方法的参数也是lambad表达式,指向的是主表中的导航属性,这里我没有为Agent表添加导航属性,所以WithMany方法的参数为空。这两个方法实际上说明了Agent表和Project表是一对多的关系。最后的OnDelete方法的参数就是删除行为了,也就是我们上面说到的DeleteBehavior的枚举值之一。

    相关文章

      网友评论

        本文标题:EF Core级联删除的设定

        本文链接:https://www.haomeiwen.com/subject/xjccjqtx.html