为了说明我的问题,假设我有一个数据模型,其中有一组书籍,每本书都有一个或多个草稿,还有一个“当前”草稿。我希望我的模型看起来像这样:
class Book
{
public int Id { get; set; }
public string Title { get; set; }
public virtual ICollection<Draft> Drafts { get; set; }
public virtual Draft CurrentDraft { get; set; }
}
class Draft
{
public int Id { get; set; }
public virtual int BookId { get; set; }
public virtual Book Book { get; set; }
public string Description { get; set; }
}
我有一个如下所示的 DbContext:
class TestDbContext : DbContext
{
public DbSet<Book> Books { get; set; }
public DbSet<Draft> Drafts { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();
base.OnModelCreating(modelBuilder);
}
}
...以及一个像这样的简单程序:
static void Main(string[] args)
{
Database.SetInitializer<TestDbContext>(new DropCreateDatabaseAlways<TestDbContext>());
using (var db = new TestDbContext())
{
var book = new Book() { Title = "War and Peace", Drafts = new List<Draft>() };
var draft1 = new Draft() { Book = book, Description = "First Draft" };
book.Drafts.Add(draft1);
var draft2 = new Draft() { Book = book, Description = "Second Draft" };
book.Drafts.Add(draft2);
book.CurrentDraft = draft2;
db.Books.Add(book);
db.SaveChanges();
foreach (var b in db.Books)
{
Console.WriteLine("Book {0}: {1}", b.Id, b.Title);
foreach (var d in book.Drafts)
Console.WriteLine("\tDraft ID {0}: {1} from Book ID {2}", d.Id, d.Description, d.BookId);
Console.WriteLine("Current draft has ID {0}", b.CurrentDraft.Id);
}
Console.ReadKey();
}
}
当EF创建DB时,它看起来像这样:
[我并不热衷于额外的 Book_Id 列,但如果它有效的话我可以接受。]
遗憾的是,当我运行测试程序时,它在 SaveChanges
调用时失败,但有一个异常(exception):
An error occurred while saving entities that do not expose foreign key properties for their relationships. The EntityEntries property will return null because a single entity cannot be identified as the source of the exception. Handling of exceptions while saving can be made easier by exposing foreign key properties in your entity types. See the InnerException for details.
我尝试在 OnModelCreating 中使用 Fluent API,但是当我尝试以这种方式配置它时,它会因为 Books 和 Drafts 之间存在两种 FK 关系而感到困惑。我对 Fluent 的东西(或者一般的 EF)不太熟悉,不知道如何正确地做到这一点。
这在 EF 代码中是否可行?
最佳答案
您的内部异常是 EF 无法确定将内容保存到数据库以正确创建内容的顺序。如果您在多个位置调用保存更改以强制测试应用程序的工作顺序:
var book = new Book() { Title = "War and Peace", Drafts = new List<Draft>() };
db.Books.Add(book);
db.SaveChanges();
var draft1 = new Draft() { Book = book, Description = "First Draft" };
book.Drafts.Add(draft1);
var draft2 = new Draft() { Book = book, Description = "Second Draft" };
book.Drafts.Add(draft2);
book.CurrentDraft = draft2;
db.SaveChanges();
关于第二个 book_id - 你可以使用这个流利的:
modelBuilder.Entity<Book>()
.HasMany(b => b.Drafts)
.WithRequired(d => d.Book)
.HasForeignKey(d => d.BookId);
modelBuilder.Entity<Book>()
.HasOptional(b => b.CurrentDraft)
.WithOptionalDependent()
.Map(m => m.MapKey("CurrentDraftId"));
生成此数据库:
关于c# - 在 EF Code First 中, Foo 是否可以拥有 Bars 集合以及 "FavouriteBar"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12805572/