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<Tag> 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
对象之前,将 post
和 tag
显式添加到 context.Posts
和 context.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约束冲突”?