1

この単純なモデルを TPH 継承でマップしてみます。

    public abstract class Master {
    public long Id {
        get;
        set;
    }
    public virtual ICollection<Detail> Details {
        get;
        set;
    }

}

public class MasterA : Master {
    public string FieldA {
        get;
        set;
    }
}

public class MasterB : Master {
    public string FieldB {
        get;
        set;
    }
}

public abstract class Detail {
    public long Id {
        get;
        set;
    }
    public long MasterId {
        get;
        set;
    }
    public Master Master {
        get;
        set;
    }
    public String CommonDetailInfo {
        get;
        set;
    }
}

public class DetailA : Detail {
    public MasterA MasterA {
        get;
        set;
    }

    public string SpecificA {
        get;
        set;
    }
}

public class DetailB : Detail {
    public MasterB MasterB {
        get;
        set;
    }
    public string SpecificB {
        get;
        set;
    }
}

マッピングは流暢な記法で行われます このように:

modelBuilder.Entity<Master>().ToTable("TestMaster");
        modelBuilder.Entity<Master>().Property(m => m.Id)
                                     .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        modelBuilder.Entity<Master>().HasKey(m => m.Id);
        modelBuilder.Entity<Master>().Map<MasterA>(m => m.Requires("MasterType").HasValue("A"));
        modelBuilder.Entity<Master>().Map<MasterB>(m => m.Requires("MasterType").HasValue("B"));

        modelBuilder.Entity<Detail>().ToTable("TestDetail");
        modelBuilder.Entity<Detail>().Property(d => d.Id)
                                     .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        modelBuilder.Entity<Detail>().HasKey(d => d.Id);
        modelBuilder.Entity<Detail>().Map<DetailA>(m => m.Requires("DetailType").HasValue("A"));
        modelBuilder.Entity<Detail>().Map<DetailB>(m => m.Requires("DetailType").HasValue("B"));

        modelBuilder.Entity<Master>()
            .HasMany(m => m.Details)
            .WithRequired(d => d.Master)
            .HasForeignKey(f => f.MasterId)
            .WillCascadeOnDelete();

EF にデータベースを作成させると、TestDetail テーブルに 2 つのフィールドが追加されます。

MasterA_Id
MasterB_Id

しかし、ベース Dteail クラスの MasterId フィールドが同じ仕事をするので、これらの 2 つのフィールドは常に Null で冗長です。

これらのフィールドをデータベースから削除し、次のようなマスター レコードの詳細を取得しようとすると:

  foreach (var detail in master.Details) {...}

「詳細」プロパティにアクセスすると、例外が発生します: 無効な ColumnName MasterA_Id、MasterB_Id。

私が間違っていることは何ですか?データベースにこれらの 2 つのフィールドを持たずに、このモデルを TPH モードでマップするにはどうすればよいですか?

ご協力いただきありがとうございます。

4

0 に答える 0