实体框架核心代码首先 - 0..1到多个关系和级联删除

时间:2016-06-29 15:02:49

标签: c# .net entity-framework entity-framework-core

我正在尝试创建一个由Entity Framework Core支持的评论系统,其中不同类型的多个实体可以附加评论。

这些是我的实体。 (在实际应用中,总共有大约7种不同的关系,但这通常看起来如何)

public class Comment : IEntityBase
{
    public int Id { get; set; }

    public int? FreezerId{ get; set; }
    public Freezer Freezer { get; set; }
    public int? BoxId{ get; set; }
    public Box Box{ get; set; }
    public string Author { get; set; }
    public DateTime CreatedAt { get; set; }
    public string Content { get; set; }
}

public class Freezer: IEntityBase
{
    public int Id { get; set; }

    public string Name { get; set; }
    public string Location { get; set; }
    public ICollection<Box> Boxes{ get; set; }
    public ICollection<Comment> Comments { get; set; }
}

public class Box: IEntityBase
{
    public int Id { get; set; }

    public Freezer Freezer{get; set;}
    public int FreezerId{get; set;}
    public string Data{ get; set; }
    public ICollection<Comment> Comments { get; set; }
}

我希望将Comment实体附加到一个冰箱或一个Box,但不能同时附加两个。

我在流畅的API中定义了以下关系:

 builder.Entity<Box>(boxBuilder=>
        {
            boxBuilder.HasOne(box=> box.Freezer)
                .WithMany(freezer => freezer.boxes)
                .HasForeignKey(box => box.FreezerId)
                .IsRequired()
                .OnDelete(DeleteBehavior.Cascade);

            boxBuilder.HasMany(box => box.Comments)
                .WithOne(comment => comment.Box)
                .HasForeignKey(comment => comment.BoxId)
                .OnDelete(DeleteBehavior.Cascade);
        });

 builder.Entity<Freezer>(freezerBuilder =>
        {
            freezerBuilder.HasMany(freezer=> freezer.Comments)
                .WithOne(comment => comment.Freezer)
                .HasForeignKey(comment => comment.FreezerId)
                .OnDelete(DeleteBehavior.Cascade);
        });

当我尝试将数据库更新为此模型时,我收到以下错误:

System.Data.SqlClient.SqlException: Introducing FOREIGN KEY constraint 'FK_Comment_Boxes_BoxId' on table 'Comment' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.

我认为错误来自于注释类中的Box和Freezer属性不是可选的,这会使 1对多 关系而不是 0..1到很多 关系这就是我想要的。

使用Entity Framework 6我只会使用.HasOptional()方法,但这并不存在于Entity Framework Core中

我认为解决这个问题的一种方法是将Comment类子类化,并为每个可以注释的实体创建一个唯一的注释类,并将外键和引用属性移动到该子类。

但感觉我不应该这样做。

1 个答案:

答案 0 :(得分:0)

您必须禁用级联删除( DeleteBehavior.Restrict ),然后它才能适用于您:

 modelBuilder.Entity<Box>(boxBuilder =>
        {
          boxBuilder.HasOne(box => box.Freezer)
              .WithMany(freezer => freezer.Boxes)
              .HasForeignKey(box => box.FreezerId)
              .IsRequired()
              .OnDelete(DeleteBehavior.Cascade);

          boxBuilder.HasMany(box => box.Comments)
              .WithOne(comment => comment.Box)
              .HasForeignKey(comment => comment.BoxId)
              .OnDelete(DeleteBehavior.Restrict);
        });

        modelBuilder.Entity<Freezer>(freezerBuilder =>
        {
          freezerBuilder.HasMany(freezer => freezer.Comments)
              .WithOne(comment => comment.Freezer)
              .HasForeignKey(comment => comment.FreezerId)
              .OnDelete(DeleteBehavior.Restrict);
        });
        base.OnModelCreating(modelBuilder);
      }

用法:

using (var myConext = new MyDbContext())
      {
        myConext.Database.EnsureCreated();
        myConext.Boxes.Add(new Box() {Freezer =  new Freezer()});
        myConext.SaveChanges();
      }