c# - 使用 Fluent API 而不是 InverseProperty 和导航属性

标签 c# entity-framework

我有一个数据库模型,模型之间的关系给 Code First 带来了一些问题。下面是一个构建的例子。

一个读者可以读过几本书,一本书可以被几个读者读过。 此外,每个读者可能都有一本最喜欢的书。

//not-working model
public class BookReader
{
    public virtual List<Book> ReadBooks { get; set; }
    public virtual Book FavoriteBook { get; set; }
    public int ID { get; set; }
}

public class Book
{
    public string BookName { get; set; }
    public int ID { get; set; }
}

这不是很好用。如果在代码中,多个读者被设置为阅读同一本书,则只有一个读者会将其保存到数据库中(大概是最后一组)。

此外,如果 BookReader.FavoriteBook 和 BookReader.ReadBooks 包含同一本书并且 db.SaveChanges() 创建了这本新书(不是现有的数据库实体),则会导致此错误:
保存不为其关系公开外键属性的实体时发生错误。

这是我对 InverseProperty 和导航属性的修复。

//working model
public class BookReader
{
    [InverseProperty("CurrentReaders")]
    public virtual List<Book> ReadBooks { get; set; }
    public virtual Book FavoriteBook { get; set; }

    public int ID { get; set; }
}

public class Book
{
    public string BookName { get; set; }
    public int ID { get; set; }
    //new, unwanted, property
    public virtual List<BookReader> CurrentReaders { get; set; }
}


我不想像这样改变模型。有没有一种方法可以在不更改模型的情况下使用 Fluent API 来完成?

我之前发过一个类似的问题,但是因为这个问题与问题无关而删除了它

最佳答案

使用 WithMany() 在 Book 实体中配置没有导航属性的多对多关系:

modelBuilder.Entity<BookReader>()
    .HasMany(r => r.ReadBooks)
    .WithMany();

这将创建以 BookReader_IDBook_ID 作为主键的联结表 BookReaderBooks。您还可以为表和键指定您自己的漂亮名称:

.WithMany().Map(mc => mc.MapLeftKey("ReaderId").MapRightKey("BookId"));

关于c# - 使用 Fluent API 而不是 InverseProperty 和导航属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18099917/

相关文章:

c# - 动态对象属性名以数字开头

c# - 在 Visual Studio 中启用 SSL - 未提示安装证书

asp.net-mvc - EntityFramework 迁移指定 web.config

c# - 连接字符串中的 %APPDATA% 未替换为实际文件夹?

sql-server - EF ObjectQuery<T> 上下文、参数、连接属性等效于 DbSet<T>

c# - MVC 中具有相同签名的方法

c# - 如何在 .NET Core 项目中引用 .NET Framework 项目?

c# - 字典的线程安全

c# - EF Core - 用于处理特定类型的全局设置

c# - 使用带有 DBContext 依赖注入(inject)的部分 View 模型实例在 _layout.cshtml 中呈现部分 View