如何解决代码优先,EF 4.1:用数据库映射以下类的最佳方法是什么?
| 亲爱的专业开发人员社区! 我正在尝试弄清楚如何使用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并运行我的代码后,我得到两个具有以下结构的表:
容器表
ID
基本表
ID
第一物业
Container_Id1
第二属性
Container_Id2
第三财产
Container_Id3
因此,我得到一个名为Base的表,该表包含具有外键的标识角色的三个标识字段。
现在的问题:
我不喜欢这种冗余。如何评估专业社区的这种情况,这正常吗?
我可以改变这个吗?我可以更清楚地了解数据库的结构吗?
映射此类的最佳方法是什么?
我已经发布了一个类似的问题,但是我仍然在意这个问题。
感谢您的答复和关注。
解决方法
默认情况下,数据库中的表结构是正常的,并且是逐层表(TPH)映射的结果。将类层次结构映射到关系数据库表是默认策略。在此策略中,所有派生类的属性都合并到一个表中,并且仅通过表中的“ discriminator”列来区分类型。
如果要在层次结构中为每个类分配单独的表,则可以使用按类型表(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
类获得一个表,该表仅包含该类的属性(示例中仅为Id
)和单独的表FirstDescendants
等,这些表具有派生类的属性。这些表通过外键关系链接,EF设法从两个表中加载所需的列,以实现您要查询的类型的对象。
您可以在此处找到有关EF如何映射类层次结构的几种策略的简介:
首先使用EF代码进行继承
编辑
我认为TPT是一种将派生类映射到关系表的更干净的方法。 TPH要求您在数据库中只为可能具有模型所需属性的映射提供可为空的列。但是另一方面,TPH的性能可能更高,因为查询不需要联接不同的表。
可能的经验法则可能是:
如果大多数属性都在基类中,而派生类仅添加了一些其他属性,则可以使用TPH。
如果基类不包含任何属性或仅包含几个属性,而大多数属性都在派生类中,则使用TPT。
但是,这种方法的优缺点以及第三种“逐表混凝土”(TPC)方法要好得多,并且在上面的链接文章系列中有详细说明。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。