c# - 代码首先,EF 4.1 : What is the best way to map the following classes with a database. ..?

标签 c# .net entity-framework code-first

亲爱的专业开发人员社区!

我试图弄清楚如何首先使用代码正确制作映射。

假设有几个类。一个容器类、一个基类和几个后代类。

基类:

public class Base {

 public int Id { get; set; }

}

后代类:

public class FirstDescendant {

 public string FirstProperty { get; set; }

}

public class SecondDescendant {

 public int SecondProperty { get; set; }

}

public class ThirdDescendant {

 public int ThirdProperty { get; set; }

}

容器类:

public class Container {

 public int Id { get; set; }

 public ICollection<FirstDescendant> FirstDescendants { get; set; }

 public ICollection<SecondDescendant> SecondDescendants { get; set; }

 public ICollection<ThirdDescendant> ThirdDescendants { get; set; }

}

默认情况下,创建 DbContext 并运行代码后,我会得到两个具有以下结构的表:

The Container table

Id

The Base table

Id

FirstProperty

Container_Id1

SecondProperty

Container_Id2

ThirdProperty

Container_Id3

因此我得到一个名为 Base 的表,其中包含相同的三个字段,这些字段具有相同的外键作用。

现在问题:

  1. 我不喜欢这种冗余。专业界如何评价这种情况,这正常吗?

  2. 我可以更改此设置吗?我可以获得更清晰的数据库结构吗?

  3. 映射此类的最佳方法是什么?

我已经发布了a similar question但我还是很关心这个问题。

感谢您的回答和关注。

最佳答案

您默认获得的数据库中的表结构是正常的,是Table-Per-Hierarchy (TPH)映射的结果。将类层次结构映射到关系数据库表是默认策略。在此策略中,所有派生类的属性都合并到一个表中,并且仅通过表中的鉴别器列来区分类型。

如果您希望层次结构中的每个类都有一个单独的表,您可以使用每个类型表 (TPT) 策略。但这不是默认设置,您必须通过数据注释明确指定...

[Table("FirstDescendants")]
public class FirstDescendant : Base
{
    public string FirstProperty { get; set; }
}
// the same with the other derived classes

...或 Fluent 代码:

modelBuilder.Entity<FirstDescendant>().ToTable("FirstDescendants");
// the same with the other derived classes

这样您就可以获得一张适合您的Base的 table 。类,仅包含此类的属性(在您的示例中仅包含 Id )和单独的表 FirstDescendants等等,它们具有派生类的属性。这些表通过外键关系链接,EF 设法从两个表中加载所需的列,以具体化您正在查询的类型的对象。

您可以在此处找到 EF 如何映射类层次结构的几种策略的介绍:

Inheritance with EF Code First

编辑

在我看来,TPT 是将派生类映射到关系表的更清晰的方法。 TPH 要求您在数据库中拥有可为空的列,仅用于您可能希望拥有模型中所需属性的映射。但另一方面,TPH 的性能可能会更高,因为查询不需要连接不同的表。

可能的决定经验法则可能是:

  • 如果大多数属性位于基类中,而派生类仅添加一些附加属性,则可以使用 TPH。

  • 如果基类不包含或仅包含少数属性,并且大多数属性都在派生类中,则使用 TPT。

但是这些方法的优点和缺点 - 也是第三种Table-Per-Concrete-Class (TPC) - 更好,并且在上面的链接文章系列中有详细解释。

关于c# - 代码首先,EF 4.1 : What is the best way to map the following classes with a database. ..?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5694257/

相关文章:

.net - System.IO.FileSystemWatcher 监视网络服务器文件夹 - 性能注意事项

c# - 无法将来自不同项目的新脚手架项目添加到我的 Web 项目 (MVC 5)

c# - 使用 JSON.Net,如果序列化 Entity Framework 对象,则禁用对数据库的访问

java - WebSocket 服务器 (Java) 无法读取但发送到 C# (Unity) 客户端

c# - 如何转换ascii字符串中的位序列c#

c# WPF TextBox 按索引检索行时出现错误?

c# - 如果我调用 C# 事件处理程序并调用它,会发生什么情况?

c# - 无法加载文件或程序集... Windows Azure 网站

c# - 提高并发字典访问效率c#

c# - 删除从客户端发送的值列表