INSERT 语句与 FOREIGN KEY 约束“FK_PostTag_Tag_TagId”冲突

Posted

技术标签:

【中文标题】INSERT 语句与 FOREIGN KEY 约束“FK_PostTag_Tag_TagId”冲突【英文标题】:The INSERT statement conflicted with the FOREIGN KEY constraint "FK_PostTag_Tag_TagId" 【发布时间】:2016-03-03 11:37:12 【问题描述】:

我正在使用 Entity Framework 7 RC1,并且我拥有以下实体:

public class Post 
  public Int32 Id  get; set; 
  public String Title  get; set; 
  public virtual IList<PostTag> PostsTags  get; set; 


public class Tag 
  public Int32 Id  get; set; 
  public String Name  get; set; 
  public virtual IList<PostTag> PostsTags  get; set; 


public class PostTag 
  public Int32 PostId  get; set; 
  public Int32 TagId  get; set; 
  public virtual Post Post  get; set; 
  public virtual Tag Tag  get; set; 

这些实体的模型配置如下:

protected override void OnModelCreating(ModelBuilder builder) 

  base.OnModelCreating(builder);

  builder.Entity<Post>(b => 

    b.ToTable("Posts");
    b.HasKey(x => x.Id);
    b.Property(x => x.Id).UseSqlServerIdentityColumn();
    b.Property(x => x.Title).IsRequired().HasMaxLength(100);
  );

  builder.Entity<Tag>(b => 
    b.ToTable("Tags");
    b.HasKey(x => x.Id);
    b.Property(x => x.Id).UseSqlServerIdentityColumn();
    b.Property(x => x.Name).IsRequired().HasMaxLength(100);
  );

  builder.Entity<PostTag>(b => 
    b.ToTable("PostsTags");
    b.HasKey(x => new  x.PostId, x.TagId );
    b.HasOne(x => x.Post).WithMany(x => x.PostsTags).HasForeignKey(x => x.PostId);
    b.HasOne(x => x.Tag).WithMany(x => x.PostsTags).HasForeignKey(x => x.TagId);
  );


我创建了迁移和数据库。然后我尝试创建一个帖子:

  Context context = new Context();

  Post post = new Post 
    PostsTags = new List<PostTag> 
      new PostTag 
        Tag = new Tag  Name = "Tag name" 
      
    ,
    Title = "Post title"
  ;

  context.Posts.Add(post);

  await _context.SaveChangesAsync();

保存时出现以下错误:

An error occurred while updating the entries. 
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_PostTag_Tag_TagId". 
The conflict occurred in database "TestDb", table "dbo.Tags", column 'Id'. 
The statement has been terminated.

有人知道这个错误的原因吗?

【问题讨论】:

【参考方案1】:

我也有同样的问题。这是我想出的解决方案。 This SO 问题对我帮助很大。

首先,如果缺少 public DbSet&lt;Tag&gt; Tags get; set; 类,请将其添加到您的 Context 类中。

然后修改帖子创建如下

Context context = new Context();
var tmpTag = new Tag  Name = "Tag name"  //add the tag to the context
context.Tags.Add(tmpTag);

Post post = new Post 
    PostsTags = new List<PostTag>(), // initialize the PostTag list
    Title = "Post title"
;    
context.Posts.Add(post);

var postTag = new PostTag() Post = post, Tag = tag; // explicitly initialize the PostTag AFTER addig both Post and Tag to context
post.PostTags.Add(postTag); // add PostTag to Post

await _context.SaveChangesAsync();

在尝试创建 PostTag 对象之前,将 posttag 显式添加到 context.Postscontext.Tags 允许 EF 在写入基础数据库时正确管理 ID。

为了完整起见,在解决了多对多关系管理的这一部分之后,我目前正在努力使用 CascadeDelete Entity Framework Core (EF7),但那是另一回事了。

【讨论】:

令人难以置信的是,我们仍然需要在 候选发布版 中解决此问题。 EF 应该能够自己找出插入顺序。【参考方案2】:

我想说你不需要在 EF CodeFirst 中明确声明你的外键,框架会为你处理它。所以从 PostTag 类中删除这些属性

public Int32 PostId  get; set; 
public Int32 TagId  get; set; 

然后从您的配置中删除这两行,然后再次尝试保存。您可能需要在保存之前更新您的数据库模型。

b.HasKey(x => new  x.PostId, x.TagId );
b.HasOne(x => x.Post).WithMany(x => x.PostsTags).HasForeignKey(x => x.PostId);
b.HasOne(x => x.Tag).WithMany(x => x.PostsTags).HasForeignKey(x => x.TagId);

【讨论】:

但是我想在我的模型上使用 FK ...我一直有一些查询,因为它真的很有用...顺便说一句,我从来没有遇到过 EF 6 的这个问题 ... 在这种情况下,你必须让你的外键可以为空。在您的示例中,您的 PostId 将为 0,这打破了 FK 约束,因为我猜您在数据库中没有 0 作为 PostId。 我怀疑是复合键导致出错 b.HasKey(x => new x.PostId, x.TagId );你真的需要这个吗?为什么没有这个课程的PK。 因为这只是一个关系表,不需要 PK 这在 SQL 中是完全有效的......但很奇怪,因为这个确切的配置在 EF 6 中有效......

以上是关于INSERT 语句与 FOREIGN KEY 约束“FK_PostTag_Tag_TagId”冲突的主要内容,如果未能解决你的问题,请参考以下文章

当插入为 NULL 时,“INSERT 语句与 FOREIGN KEY 约束冲突”

Asp.net core Identity “INSERT 语句与 FOREIGN KEY 约束冲突”

INSERT 语句与 FOREIGN KEY 约束“FK_PostTag_Tag_TagId”冲突

如何编写检查以避免消息“INSERT语句与FOREIGN KEY约束冲突”?

SqlException:INSERT 语句与 FOREIGN KEY 约束冲突 - asp.net-core

ALTER TABLE 语句与 FOREIGN KEY 约束冲突