2

我有一个我正在定义的一些实体的抽象基类。其中一个派生实体实际上是另一个实体的非抽象基类。

遵循此代码:

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; }
}
4

1 回答 1

2

问题不在于第二级继承,而是PerformanceReportEntry(的基础ByPeriodPerformanceReportEntry)是一个实体,而BaseReportEntry(的基础PerformanceReportEntry)不是。

如果不是实体,您的映射将起作用PerformanceReportEntry- 即它的映射未添加到模型构建器配置中,并且您没有DbSet此类型,并且它不会出现在ReportsBundle.

在这种情况下,无法从中派生配置BaseReportEntryMap<ByPeriodPerformanceReportEntry>- 并且没有必要,因为基本属性的映射已经由BaseReportEntryMap<PerformanceReportEntry>. 因此你可以使用

public class ByPeriodPerformanceReportEntryMap
    : EntityTypeConfiguration<ByPeriodPerformanceReportEntry>

但我怀疑生成的模型是否如您所料。我不知道里面的PerformanceReportEntriesByPeriodPerformanceReportEntries集合ReportsBundle应该表达什么。您是否期望这ByPeriodPerformanceReportEntries是按子类型过滤的集合?您是否期望PerformanceReportEntries它只包含PerformanceReportEntrys 但不是ByPeriodPerformanceReportEntrys 的 ReportsEntries?您是否期望PerformanceReportEntries包含所有条目,包括ByPeriodPerformanceReportEntries?

无论如何,BaseReportEntry.ReportBundle是映射在PerformanceReportEntry(而不是ByPeriodPerformanceReportEntry)中的导航属性。这意味着类中的反向导航属性ReportsBundle必须引用PerformanceReportEntry哪个是PerformanceReportEntries导航集合。将在andByPeriodPerformanceReportEntries之间引入第二个一对多关系(在 中没有导航属性)。的反向导航属性不会是。ReportsBundleByPeriodPerformanceReportEntryByPeriodPerformanceReportEntryByPeriodPerformanceReportEntriesBaseReportEntry.ReportBundle

我的感觉是你不应该拥有这个ReportsBundle.ByPeriodPerformanceReportEntries集合,但我不确定你想要达到什么目的。

编辑

参考您的评论,您只有这两种报告类型,我认为您的映射太复杂了。我会做以下事情:

  • 删除BaseReportEntry该类并将其属性移动到PerformanceReportEntry. 拥有一个只派生一个其他类的基类是没有意义的。

  • 删除ByPeriodPerformanceReportEntriesfrom ReportsBundle,这ReportsBundle将是:

    public class ReportsBundle 
    {
        public int ReportsBundleId { get; set; }
        public virtual ICollection<PerformanceReportEntry>
            PerformanceReportEntries { get; set; }
    }
    
  • 删除BaseReportEntryMap并将映射移动到PerformanceReportEntryMap. 从 导出此地图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>并指定映射,而不是为基本属性再次指定映射。那已经发生在. 您不需要也不能再次指定它,因为它会导致您遇到的异常。ByPeriodPerformanceReportEntryPerformanceReportEntryMap

  • 使用 Table-Per-Hierarchy (TPH) 继承而不是 Table-Per-Concrete-Type (TPC),尤其是当您在ByPeriodPerformanceReportEntry. TPC 更难使用,因为它在数据库生成的身份和多态关联(在 和 之间的关系中存在PerformanceReportEntry)存在问题ReportsBundle这些问题在这里有更详细的解释。相反,TPH 提供了最佳性能。ByPeriodPerformanceReportEntryMap然后看起来像这样:

    public class ByPeriodPerformanceReportEntryMap
        : EntityTypeConfiguration<ByPeriodPerformanceReportEntry>
    {
        public ByPeriodPerformanceReportEntryMap()
        {
            this.Property(e => e.Period).IsRequired();
        }
    }
    

    TPH 不需要显式配置,因为它是默认继承映射。

于 2013-03-25T00:24:58.687 回答