INSERT 语句与 Entity Framework Core 中的 FOREIGN KEY 约束冲突
The INSERT statement conflicted with the FOREIGN KEY constraint in 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: The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Book_Author_AuthorAuthorId".
这个简单的插入有什么问题?我不想手动添加 BookPage 和 Author,这是 Entity Framework 工作。
在您的 ApplicationDbContext
class 中,您必须为 Author
class 和 BookPage
[=42] 添加一个 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服务器.
您可以查看此 post 了解更多信息:
- What are the best practices for using a GUID as a primary key, specifically regarding performance?
另一种方法是使用标识列作为主键并添加具有唯一约束的另一列(将包含唯一 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();
}
我正在使用 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: The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Book_Author_AuthorAuthorId".
这个简单的插入有什么问题?我不想手动添加 BookPage 和 Author,这是 Entity Framework 工作。
在您的 ApplicationDbContext
class 中,您必须为 Author
class 和 BookPage
[=42] 添加一个 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服务器.
您可以查看此 post 了解更多信息:
- What are the best practices for using a GUID as a primary key, specifically regarding performance?
另一种方法是使用标识列作为主键并添加具有唯一约束的另一列(将包含唯一 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();
}