【问题标题】:The INSERT statement conflicted with the FOREIGN KEY constraint in Entity Framework CoreINSERT 语句与 Entity Framework Core 中的 FOREIGN KEY 约束冲突
【发布时间】:2016-08-01 13:39:14
【问题描述】:

我正在使用 Entity Framework 7 RC1,我有这些实体:

public class Book
{
    [Key]
    public string BookId { get; set; }
    public List<BookPage> Pages { get; set; }
    public Author Author { get; set; }
    public string Text { get; set; }
} 

public class BookPage
{
    [Key]
    public string BookPageId { get; set; }
    public int Number { get; set; }
}

public class Author
{
    [Key]
    public string AuthorId { get; set; }
    public string FullName { get; set; }
}

ApplicationDbContext.cs 是默认的,public DbSet&lt;Book&gt; Books { get; set; }

当我尝试插入新书时,像这样

var book = new Book()
{
    BookId = Guid.NewGuid().ToString(),
    Pages = new List<BookPage>()
    {
        new BookPage()
        {
            BookPageId = Guid.NewGuid().ToString(),
            Number = 1
        }
    },
    Author = new Author()
    {
        AuthorId = Guid.NewGuid().ToString(),
        FullName = "Forexample"
    },
    Text = "new book"
};
dbContext.Books.Add(book);
dbContext.SaveChanges();

抛出异常:

SqlException:INSERT 语句与 FOREIGN KEY 约束“FK_Book_Author_AuthorAuthorId”冲突。

这个简单的插入有什么问题?我不想手动添加 BookPage 和 Author,这是实体框架的工作。

【问题讨论】:

  • 记录可能已经存在。
  • @AmitKumarGhosh 不,数据库为空
  • 如果您的 id 是 Guid,为什么要使用 string?另外我很确定你必须dbContext.BookPages.AddBookPages 和新的Author 相同。
  • 尝试先在各自的表中添加 BookPage 和 Author,然后在 Book 的 BookPage 和 Author 中使用相同的 Guid。
  • @PKV 这是一个简单的例子,但是如果我有更多的实体,我应该如何处理它们?手动向数据库添加一百个 if 实体?

标签: c# entity-framework entity-framework-core


【解决方案1】:

在您的ApplicationDbContext 类中,您必须为Author 类和BookPage 类添加一个DbSet

public class ApplicationDbContext : DbContext
{
    public DbSet<Book> Books { get; set; }

    public DbSet<BookPage> BookPages { get; set; }

    public DbSet<Author> Authors { get; set; }

    ...
}

这样你就可以这样重写你的代码:

var author = dbContext.Authors.Add(new Author()
{
    AuthorId = Guid.NewGuid().ToString(),
    FullName = "Forexample"
}).Entity;

var page = dbContext.BookPages.Add(new BookPage()
{
    BookPageId = Guid.NewGuid().ToString(),
    Number = 1
}).Entity;


var book = new Book.Book()
{
    BookId = Guid.NewGuid().ToString(),
    Pages = new List<BookPage>(),
    Text = "new book"
};
book.Pages.Add(page);
book.Author = author ;
dbContext.Books.Add(book);
dbContext.SaveChanges();

无论如何您不应该将Guid 用作主键(实际上是作为聚集索引),这是使用 SQL Server 的一种不好的做法。

您可以查看此帖子以获取更多信息:

另一种方法是使用标识列作为主键并添加具有唯一约束的其他列(将包含唯一 id),以便您的模型看起来像这样:

public class Author
{
    public Author()
    {
        AuthorUid = Guid.NewGuid();
    }

    public int AuthorId { get; set; }
    public Guid AuthorUid { get; set; }
    public string FullName { get; set; }
}

public class Book
{
    public Book()
    {
        BookUid = Guid.NewGuid();
        Pages = new List<BookPage>();
    }

    public int BookId { get; set; }
    public Guid BookUid { get; set; }
    public List<BookPage> Pages { get; set; }
    public Author Author { get; set; }
    public string Text { get; set; }
}

public class BookPage
{
    public BookPage()
    {
        BookPageUid = Guid.NewGuid();
    }

    public int BookPageId { get; set; }
    public Guid BookPageUid { get; set; }
    public int Number { get; set; }
}

在您的DbContext 中,您可以指定唯一约束:

public class BookContext : DbContext
{
    public DbSet<Book> Books { get; set; }

    public DbSet<BookPage> BookPages { get; set; }

    public DbSet<Author> Authors { get; set; }

    ...

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Author>().HasAlternateKey(a => a.AuthorUid);
        modelBuilder.Entity<Book>().HasAlternateKey(a => a.BookUid);
        modelBuilder.Entity<BookPage>().HasAlternateKey(a => a.BookPageUid);
    }
}

然后像这样添加你的新实体:

using (var dbContext = new BookContext())
{
    var author = dbContext.Authors.Add(new Author()
    {
        FullName = "Forexample"
    }).Entity;

    var page = dbContext.BookPages.Add(new BookPage()
    {
        Number = 1
    }).Entity;

    var book = new Book.Book()
    {
        Text = "new book"
    };

    book.Pages.Add(page);
    book.Author = author;

    dbContext.Books.Add(book);
    dbContext.SaveChanges();
}

【讨论】:

  • 什么意思?不必将其添加到 DbSet 中?
  • 是的,只创建书,里面有书页和作者,然后添加到 DbSet 中。
  • 我不这么认为,因为您需要将作者和书页附加到 EF 上下文中。但我会帮你检查一下
  • 是的,你需要明确告诉 EF 你要插入哪个元素
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-28
  • 1970-01-01
相关资源
最近更新 更多