2016-03-03 137 views
0

我使用实体框架7 RC1和我有实体:INSERT语句冲突与外键约束“FK_PostTag_Tag_TagId”

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. 

有谁知道这个错误的原因是什么?

回答

0

我会说你不需要在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); 
+0

但是我想在我的模型上使用FK ...我总是有几个查询它是真的有用...顺便说一句,我从来没有与EF 6这个问题... –

+0

在这种情况下,你有使您的外键可以为空。在你的例子中,你的PostId将为0,这是打破FK约束,因为我猜你没有0作为DB中的PostId。 –

+0

我得到了同样的错误,甚至使两个键可空... –

1

我有同样的问题。这是我提出的解决方案。 This这个问题帮了我很多。

首先,如果缺失,请将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对象之前显式地将两者posttagcontext.Postscontext.Tags允许EF正确管理的ID而写入底层数据库。

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

+0

我们仍然需要解决这个问题*发布候选*。 EF应该能够确定插入顺序本身。 –