0

我正在尝试使用 EF5 Code First,并且正在使用模型(如下所示)。

当我查看创建的数据库时,我感到很困惑,因为我在 Track 表中没有看到任何指向 Category 表的内容。Category 有一个 FK 指向 Track,但这意味着会有重复的类别?

一点背景知识:我正在尝试构建一个有轨道的模型,每个轨道可以有 1 到 N 个类别。所有类别都已定义,即它们基本上是一个查找,我计划在创建数据库时在种子方法中创建它们。

我想我没有理解一些明显的东西......当我查询一个轨道时,我怎么知道它包含什么类别?

谢谢

public class Track : IAuditInfo
{
    public Int32 Id { get; set; }
    public String Name { get; set; }
    public String Description { get; set; }
    public String Data { get; set; }
    public DateTime CreatedOn { get; set; }
    public DateTime ModifiedOn { get; set; }

    public ICollection<Category> Categories { get; set; }

    public Track()
    {
        Categories = new List<Category>();
    }
}

public class Category
{
    public Int32 Id { get; set; }
    public Boolean IsVisible { get; set; }
    public String DisplayName { get; set; }
}
4

2 回答 2

1

您当前的模型是曲目和类别之间的一对多关系。正如您已经注意到实体框架所做的那样,这通常使用多侧(类别)到一侧(轨道)的外键来实现。

如果我理解正确的话,你想要的是多对多的关系。许多曲目可以与同一个类别相关,而单个曲目可以属于许多类别。

要让实体框架了解您需要多对多关系,您只需将 ICollection 属性添加到类别类即可。所以你的两个类都应该有另一个类的集合。即轨道有很多类别,类别有很多轨道。

有关更多信息,您还可以查看:http: //msdn.microsoft.com/en-us/data/hh134698.a.nospx

于 2013-10-10T05:44:54.347 回答
0

Olav 是对的,您目前的数据模型并没有告诉实体框架其中存在多对多关系。

解决此问题的最简单方法是添加

public virtual ICollection<Track> Tracks { get; set; }

到你的Category班级。

但是...您可能不想用与您的领域无关的人工制品污染您的领域模型。更重要的是,当您这样做时,由实体框架决定调用绑定表的内容。在 EF6 之前,此命名是不确定的(请参阅http://entityframework.codeplex.com/workitem/1677),这可能意味着编译相同代码的两台不同机器将决定该表的不同名称并导致一些有趣的迁移问题在您的生产系统中。

这两个问题的答案是始终使用 Fluent Configuration 显式管理多对多关系。

在您的 Data Context 类中,覆盖OnModelCreating,如下所示:

public class MyDb : DbContext
{
    public IDbSet<Track> Tracks { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Track>()
           .HasMany(t => t.Categories)
           .WithMany()
           .Map(c => c.ToTable("CategoriesForTracks"));
    }
} 

如果这样做,则不需要向 Category 类添加导航属性,尽管您仍然可以(如果这样做,您应该使用允许您指定属性的 WithMany 的重载)。

实体之间的关系以及如何将其映射到关系数据库本身就很困难。对于除了最简单的父子关系之外的任何事情,您都需要使用 fluent API 来确保您确实得到了您想要的。

Morteza Manavi 有一个非常好的博客系列,详尽地描述了 EF Code First 中的关系。

注意 您通常应该将导航属性设置为虚拟的。所以,你应该Category像这样改变你的班级:

public virtual ICollection<Category> Categories { get; set; }

从理论上讲,不使其成为虚拟应该只会导致急切加载而不是延迟加载。在实践中,当我的导航属性不是虚拟的时,我总是会发现很多细微的错误。

于 2013-10-10T12:09:08.970 回答