我有一个用于我定义的一些实体的抽象基类。这些派生实体之一实际上是另一个实体的非抽象基类。
按照此代码:
public abstract class BaseReportEntry {
public int ReportEntryId { get; set;}
public int ReportBundleId { get; set; } //FK
public virtual ReportBundle ReportBunde { get; set; }
}
//A few different simple pocos like this one
public PerformanceReportEntry : BaseReportEntry {
public int PerformanceAbsolute { get; set; }
public double PerformanceRelative { get; set; }
}
//And one with a second level of inheritance
public ByPeriodPerformanceReportEntry : PerformanceReportEntry {
public string Period { get; set; }
}
我正在使用基本EntityTypeConfiguration
:
public class BaseReportEntryMap<TReportEntry> : EntityTypeConfiguration<TReportEntry>
where TReportEntry : BaseReportEntry
{
public BaseReportEntryMap()
{
this.HasKey(e => e.ReportEntryId);
this.HasRequired(e => e.ReportsBundle)
.WithMany()
.HasForeignKey(e => e.ReportsBundleId);
}
}
大概这对于一级继承来说效果很好,但对于具有第二级继承的情况会抛出以下错误:
The foreign key component 'ReportsBundleId' is not a declared property on type 'ByPeriodPerformanceReportEntry'
public class ByPeriodPerformanceReportEntryMap : BaseReportEntryMap<ByPeriodPerformanceReportEntry>
{
public ByPeriodPerformanceReportEntryMap ()
: base()
{
this.Property(e => e.Period).IsRequired();
this.Map(m =>
{
m.MapInheritedProperties();
m.ToTable("ByPeriodPerformanceReportEntries");
});
}
}
如果需要,这里是 ReportBundle 类
public class ReportsBundle
{
public int ReportsBundleId { get; set; }
public virtual ICollection<PerformanceReportEntry> PerformanceReportEntries{ get; set; }
public virtual ICollection<ByPeriodPerformanceReportEntry> ByPeriodPerformanceReportEntries{ get; set; }
}
最佳答案
问题不在于第二级继承,而在于 PerformanceReportEntry
( ByPeriodPerformanceReportEntry
的基数)是一个实体,而 BaseReportEntry
( PerformanceReportEntry
的基数)不是。
如果PerformanceReportEntry
,您的映射将起作用。不会是一个实体 - 即它的映射不会添加到模型构建器配置中,并且您没有 DbSet
对于这种类型,它不会出现在 ReportsBundle
中的导航集合中.
从 BaseReportEntryMap<ByPeriodPerformanceReportEntry>
派生配置在这种情况下是不可能的 - 并且没有必要,因为基本属性的映射已经由 BaseReportEntryMap<PerformanceReportEntry>
发生。 。因此您可以使用
public class ByPeriodPerformanceReportEntryMap
: EntityTypeConfiguration<ByPeriodPerformanceReportEntry>
但我怀疑生成的模型是否如您所期望的那样。我不知道PerformanceReportEntries
是什么和ByPeriodPerformanceReportEntries
收藏 ReportsBundle
应该表达。你期望吗ByPeriodPerformanceReportEntries
是按子类型过滤的集合吗?你期望吗PerformanceReportEntries
仅包含 PerformanceReportEntry
的 ReportsEntries s 但不是ByPeriodPerformanceReportEntry
是?你期望吗PerformanceReportEntries
包含所有条目,包括 ByPeriodPerformanceReportEntries
?
无论如何,BaseReportEntry.ReportBundle
是映射在 PerformanceReportEntry
中的导航属性(不在 ByPeriodPerformanceReportEntry
中)。这意味着类 ReportsBundle
中的反向导航属性必须引用PerformanceReportEntry
这是 PerformanceReportEntries
导航集合。 ByPeriodPerformanceReportEntries
将在 ReportsBundle
之间引入第二个一对多关系和ByPeriodPerformanceReportEntry
( ByPeriodPerformanceReportEntry
中没有导航属性)。 ByPeriodPerformanceReportEntries
的逆向导航属性不会是BaseReportEntry.ReportBundle
.
我的感觉是你不应该有 ReportsBundle.ByPeriodPerformanceReportEntries
集合,但我不确定你到底想要实现什么。
编辑
根据您的评论,您只有这两种报告类型,我认为您的映射太复杂了。我会执行以下操作:
删除
BaseReportEntry
类并将其属性移至PerformanceReportEntry
。拥有一个只有一个其他类派生自的基类是没有意义的。删除
ByPeriodPerformanceReportEntries
来自ReportsBundle
,这样ReportsBundle
将是:public class ReportsBundle { public int ReportsBundleId { get; set; } public virtual ICollection<PerformanceReportEntry> PerformanceReportEntries { get; set; } }
删除
BaseReportEntryMap
并将映射移至PerformanceReportEntryMap
。此 map 源自EntityTypeConfiguration<PerformanceReportEntry>
.更正映射。目前这是错误的,因为您没有在
WithMany
中指定反向导航属性。 。PerformanceReportEntryMap
应该看起来像这样:public class PerformanceReportEntryMap : EntityTypeConfiguration<PerformanceReportEntry> { public PerformanceReportEntryMap() { this.HasKey(e => e.ReportEntryId); this.HasRequired(e => e.ReportsBundle) .WithMany(b => b.PerformanceReportEntries) .HasForeignKey(e => e.ReportsBundleId); } }
派生
ByPeriodPerformanceReportEntryMap
来自EntityTypeConfiguration<ByPeriodPerformanceReportEntry>
并仅指定ByPeriodPerformanceReportEntry
中声明的属性的映射,不再是基本属性。这已经发生在PerformanceReportEntryMap
。您不需要也不能再次指定它,因为它会导致您遇到的异常。使用每个层次结构表 (TPH) 继承,而不是每个具体类型表 (TPC),特别是如果您只有
ByPeriodPerformanceReportEntry
中声明的几个属性。 。 TPC 更难使用,因为它在数据库生成的身份和多态关联(在PerformanceReportEntry
和ReportsBundle
之间的关系中存在)方面存在问题。 The problems are explained in more details here 。相反,TPH 提供最佳性能。ByPeriodPerformanceReportEntryMap
然后看起来像这样:public class ByPeriodPerformanceReportEntryMap : EntityTypeConfiguration<ByPeriodPerformanceReportEntry> { public ByPeriodPerformanceReportEntryMap() { this.Property(e => e.Period).IsRequired(); } }
无需显式配置 TPH,因为它是默认继承映射。
关于entity-framework - EF Code First 配置中的多级继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15604585/