tl;dr : コード ファースト モデルを、オブジェクトの特定の階層が混合継承スキームを持つ既存のデータベースにマップしようとしています。一部の具象クラスは TPH を使用し、一部は TPT を使用します。マッピングを正しく取得できないようです。
既存のデータベースにマップしようとしているオブジェクトの階層があります。一部の具象クラスには追加のプロパティが含まれているため、独自のテーブルがあります。一部の具象クラスはそうではないため、ベース テーブルに存在し、識別子列に依存します。簡単にするために、POC を作成しました。データベース構造は次のようになります。
CREATE TABLE Foos (
Id INT IDENTITY NOT NULL PRIMARY KEY,
FooType TINYINT NOT NULL
)
CREATE TABLE FooTpts (
Id INT NOT NULL PRIMARY KEY
FOREIGN KEY REFERENCES Foos(Id),
Value INT NOT NULL
)
同等の POCO は次のようになります。
public abstract class Foo
{
public int Id { get; set; }
}
public class FooTph : Foo {}
public class FooTpt : Foo
{
public int Value { get; set; }
}
十分に単純に思えます。したがって、私の最初の試みは次のマッピングでした(流暢または属性を使用しても、結果は同じです):
modelBuilder.Entity<Foo>()
.ToTable("Foos")
.Map<FooTph>(m => m.ToTable("Foos").Requires("FooType").HasValue(1))
.Map<FooTpt>(m => m.ToTable("FooTpts").Requires("FooType").HasValue(2));
しかし、それはうまくいきませんでした:
- テーブルに
FooTpt.FooType
記述子を作成したいFooTpts
コマンドを実行しようとすると、次のエラーが表示されます (おそらく上記のポイント 1 が原因です)。
(6,10) : エラー 3032: 6 行目から始まるフラグメントのマッピングの問題、11:EntityTypes ConsoleApplication1.FooTph、ConsoleApplication1.FooTpt がテーブル Foo の同じ行にマップされています。マッピング条件を使用して、これらのタイプがマップされる行を区別できます。
ふりだしに戻る。この回答は、親 (TPH) テーブルにマップされた中間抽象エンティティを作成することを提案しています。すべては、別の抽象化レイヤーでいつでも解決できますよね? だから私はいくつかの変更を加えます:
+ public abstract class FooTptBase : Foo {}
- public class FooTpt : Foo
+ public class FooTpt : FooTptBase
マッピングを変更します。
modelBuilder.Entity<Foo>()
.ToTable("Foos")
.Map<FooTph>(m => m.ToTable("Foos").Requires("FooType").HasValue(1))
.Map<FooTptBase>(m => m.ToTable("Foos").Requires("FooType").HasValue(2));
modelBuilder.Entity<FooTpt>().ToTable("FooTpts");
データベースは正常に表示され、親テーブルには単一の識別子があります。しかし、まだ何かが不足しており、同じエラーが発生します。
(6,10) : エラー 3032: 6 行目から始まるフラグメントのマッピングの問題、11:EntityTypes ConsoleApplication1.FooTph、ConsoleApplication1.FooTpt がテーブル Foo の同じ行にマップされています。マッピング条件を使用して、これらのタイプがマップされる行を区別できます。
すべてFooTpt
の s はFooTptBase
定義上 である必要があり、これには が必要なため、これはあまり意味がありませんFooType == 2
。(モデル ビルダーが私の中間FooTptBase
抽象型を無視しているように見えますか?)
それで、私は何が欠けていますか?自分がやろうとしていることをどのように達成できますか?