提问者:小点点

INSERT语句与外键约束“FK _邮政标签_标签标识”冲突


我使用实体框架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.

有谁知道此错误的原因?


共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);

匿名用户

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

首先,添加一个公共数据库集

然后修改帖子创建,如下所示

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();

post标记显式添加到上下文。在尝试创建PostTag对象之前发布上下文和context。这使EF能够在向底层DB写入时正确管理ID。

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