使用Fluent API代替InverseProperty和导航属性

时间:2013-08-07 09:38:47

标签: 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; }
}

这不太好用。如果在代码中,多个读取器被设置为已读取同一本书,则只有其中一个读取器将其保存到db(可能是最后一组)。

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

以下是我对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完成此操作?

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

1 个答案:

答案 0 :(得分:4)

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

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

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

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