2

定義しているいくつかのエンティティの抽象基本クラスがあります。これらの派生エンティティの1つは、実際には別のエンティティに対する非抽象基本クラスです。

このコードに従う:

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

おそらく、これは1レベルの継承では正常に機能しますが、2番目のレベルがある1つのケースでは、次のエラーをスローします。

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

問題は、継承の第2レベルではありませんが、PerformanceReportEntry(のベースByPeriodPerformanceReportEntry)がエンティティであるのに対し、BaseReportEntry(のベース)はエンティティでPerformanceReportEntryはありません。

エンティティでない場合PerformanceReportEntry、マッピングは機能します。つまり、そのマッピングはモデルビルダー構成に追加されずDbSet、このタイプには対応せず、のナビゲーションコレクションでは発生しませんReportsBundle

この場合、から構成をBaseReportEntryMap<ByPeriodPerformanceReportEntry>取得することはできません。また、基本プロパティのマッピングは。によって既に行われているため、必要ありませんBaseReportEntryMap<PerformanceReportEntry>。したがって、あなたは使用することができます

public class ByPeriodPerformanceReportEntryMap
    : EntityTypeConfiguration<ByPeriodPerformanceReportEntry>

しかし、結果として得られるモデルが期待どおりであるかどうかは疑問です。PerformanceReportEntriesのとByPeriodPerformanceReportEntriesコレクションが何ReportsBundleを表現するのかわかりません。ByPeriodPerformanceReportEntriesそれがサブタイプによってフィルタリングされたコレクションだと思いますか?sであるがsPerformanceReportEntriesではないReportsEntriesのみが含まれていると思いますか??を含むすべてのエントリが含まれていると思いますか?PerformanceReportEntryByPeriodPerformanceReportEntryPerformanceReportEntriesByPeriodPerformanceReportEntries

とにかく、(ではなく)にBaseReportEntry.ReportBundleマップされたナビゲーションプロパティです。つまり、クラスの逆ナビゲーションプロパティは、ナビゲーションコレクションがどれであるかを参照する必要があります。との間の2番目の1対多の関係を導入します(のナビゲーションプロパティなし)。の逆ナビゲーションプロパティはになりません。PerformanceReportEntryByPeriodPerformanceReportEntryReportsBundlePerformanceReportEntryPerformanceReportEntriesByPeriodPerformanceReportEntriesReportsBundleByPeriodPerformanceReportEntryByPeriodPerformanceReportEntryByPeriodPerformanceReportEntriesBaseReportEntry.ReportBundle

私はあなたがコレクションを持っているべきではないと感じていますが、あなたがReportsBundle.ByPeriodPerformanceReportEntries正確に何を達成したいのかわかりません。

編集

私の意見では、これら2つのレポートタイプしかないというコメントを参照すると、マッピングが非常に複雑です。私は次のことをします:

  • BaseReportEntryクラスを削除し、そのプロパティをに移動しますPerformanceReportEntry。他の1つのクラスだけが派生する基本クラスを持つことは意味がありません。

  • ByPeriodPerformanceReportEntriesからを削除すると、次ReportsBundleのようにReportsBundleなります。

    public class ReportsBundle 
    {
        public int ReportsBundleId { get; set; }
        public virtual ICollection<PerformanceReportEntry>
            PerformanceReportEntries { get; set; }
    }
    
  • を削除しBaseReportEntryMap、マッピングをに移動しPerformanceReportEntryMapます。からこのマップを取得しますEntityTypeConfiguration<PerformanceReportEntry>

  • マッピングを修正します。で逆ナビゲーションプロパティを指定していないため、現在は間違っていますWithManyPerformanceReportEntryMap次のようになります。

    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-Concrete-Type(TPC)の代わりにTable-Per-Hierarchy(TPH)継承を使用します。特に、で宣言されているプロパティが少ない場合はそうですByPeriodPerformanceReportEntry。TPCは、データベースで生成されたIDと、多態的な関連付け(との間の関係にある)に問題があるため、使用がより困難PerformanceReportEntryですReportsBundle問題については、こちらで詳しく説明しています。代わりに、TPHが最高のパフォーマンスを提供します。ByPeriodPerformanceReportEntryMapその場合、次のようになります。

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

    TPHはデフォルトの継承マッピングであるため、明示的な構成は必要ありません。

于 2013-03-25T00:24:58.687 に答える