INSERT語句與Entity Framework Core中的FOREIGN KEY約束衝突

c# entity-framework entity-framework-core

我正在使用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<Book> 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,它是Entity Framework的工作。

一般承認的答案

在你ApplicationDbContext類,你必須添加一個DbSetAuthor類和程序BookPage類:

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的一個不好的做法。

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

另一種方法是使用標識列作為主鍵,並添加一個具有唯一約束的其他列(將包含唯一標識),以便您的模型看起來像這樣:

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


Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow