如何使用EF将三角形关系插入数据库



>你好,我有一个数据库,里面有 3 个表,设计成三角形,如下所示:

File  has many Page 
Page  has many Segment
File  has many Segment

当我尝试插入类型为File的实体时,出现以下错误:

  • InnerException {"MERGE 语句与 FOREIGN KEY 约束 \"FK_Segment_File_FileId\" 冲突。冲突发生在 数据库 \"我的数据库", 表 \"dbo.文件\",列"Id"。\rThe 语句已终止。 系统异常 {Microsoft.Data.SqlClient.SqlException}

模型

public class File
{
public int Id{get;set;}
public ICollection<Segment> Segments{get;set;}
public ICollection<Pages> Pages{get;set;}
}
public class Page
{
public int Id{get;set;}
public ICollection<Segment> Segments{get;set;}
}
public class Segment
{
public int Id{get;set;}
public Page Page{get;set;}
public int PageId{get;set;}  //foreign key from page
public File File{get;set;}
public int FileId{get;set;} //foreign key from file
}

上下文

public class MyContext: DbContext {
public DbSet<Segment> Segments { get; set; }
public DbSet<Page> Pages { get; set; }
public DbSet<File> Files { get; set; }
public SXSContext(DbContextOptions<MyContext> options):base(options) {
}
protected override void OnModelCreating(ModelBuilder modelBuilder) {
modelBuilder.Entity<File>(ent => {
ent.ToTable("File");
ent.HasKey(x => x.Id);
ent.Property(x => x.Id).IsRequired();
});
modelBuilder.Entity<Page>(ent => {
ent.ToTable("Page");
ent.HasKey(x => x.Id);
ent.Property(x => x.Id).IsRequired();
ent.Property(x => x.FileId).IsRequired();
ent.HasOne(y => y.File).WithMany(t => t.Pages).HasForeignKey(g => g.FileId).OnDelete(DeleteBehavior.NoAction);
});
modelBuilder.Entity<Segment>(ent => {
ent.ToTable("Segment");
ent.HasKey(x => x.Id);
ent.Property(x => x.Id).IsRequired();
ent.Property(x => x.PageId).IsRequired();
ent.Property(x => x.FileId).IsRequired();
ent.HasOne(y => y.Page).WithMany(t => t.Segments).HasForeignKey(g => g.PageId).OnDelete(DeleteBehavior.Cascade);
ent.HasOne(y => y.File).WithMany(t => t.Segments).HasForeignKey(g => g.FileId).OnDelete(DeleteBehavior.Cascade);
});
}
}

用法

static async Task Main(string[] args) {
await Task.Delay(1);
DbContextOptionsBuilder<MyContext> optionsBuilder = new DbContextOptionsBuilder<MyContext>();
optionsBuilder.UseSqlServer(connectionString);
SXSContext context = new SXSContext(optionsBuilder.Options);
context.Database.EnsureCreated();
List<Page> pages = new List<Page>{
new Page{
Segments = new List<Segment> {
new Segment{  },
new Segment{  },
new Segment{ }}
},
new Page{
Segments = new List<Segment> {
new Segment{  },
new Segment{  }}
}
};
File file = new File {  Pages = pages };
context.Files.Add(file);
context.SaveChanges();
int val = await context.SaveChangesAsync();
}

附言我Segment的外键作为required,它们可能会在父母FilePage之前插入,这可能是一个问题吗?

应该如何插入这样的模式?我从File开始,我有PagesSegments它们在插入之前不会id

。它们可以插入一个操作中,还是必须从根开始插入,在我的情况下是File

我有类似的问题,这是我遵循的解决方法:

首先,您应该插入非依赖实体并触发SaveChanges / SaveChangesAsync以便您的实体将获得 id-s(有关更多信息,请查看来自另一个线程的答案(,在您的情况下,首先您必须添加File并调用SaveChanges / SaveChangesAsync,然后您应该对Page做同样的事情,每一步之后,您都会填写 id-s。 之后,您可以使用第三个插入(在您的情况下是Segment(,而不会出现任何错误,因为您可以拥有所有引用的 id-s。

最新更新