Entity Framework 4.1 データ ストアに格納したいオブジェクトの階層があるとします。Code First を使用して作成しています。それらは次のようになります。
BasicState
has many -> StatefulEntities
has a -> CreationDate
ReceivedState
has a -> EntityLocation
ApprovedState
has a -> EntityLocation
OrderedState
has a -> Order
DispatchedState
has a -> Order
has a -> DispatchNumber
はBasicState
他のすべての状態の親であり、他のすべてはこれら 2 つのフィールド/関係を共有します。
私の最初の考え、およびこれを実装した方法は、Table Per Hierarchy 継承を使用することでした。なぜならBasicState
、これらの共通プロパティから継承して、他の状態に参加させることができるように思われたからです。
ただし、異なる状態がフィールドを共有する場合、基礎となるデータ モデルは共有しないため、問題が発生しました。たとえば、私のデータベースはEntityLocation_Id
一方からReceivedState
と他方ApprovedState
からのものEntityLocation_Id1
です。どのフィールドがどのモデルに属しているかがわからないため、テスト データを作成するのが難しくなります。これについては以前質問しました。
私が行った解決策は、次のようなものでした。
public abstract class BaseState
{
public DateTime CreatedDate { get; set; }
public ICollection<StatefulEntity> StatefulEntities{get;set;}
}
public abstract class LocationState : BaseState
{
public Location EntityLocation { get; set; }
}
public class ReceivedState : LocationState
{
}
public class ApprovedState : LocationState
{
}
これは部分的に機能しましたが、単一のものを作成しましたが、同じように動作し、実装は区別できませんが、とのEntityLocation_Id
2 つOrder_Ids
を作成しました。OrderedState
DispatchedState
そのほとんど半分が解決されたので、私はこの質問をするように導く別の問題にぶつかりました:
BasicState
との関係がStatefulEntities
両方向で多対多であることを考えるとOrderedStates
、 a に属するから注文の詳細を見つけることができる必要がありStatefulEntity
ます。
BasicState
問題は、これは SQL で表現するのは非常に簡単ですが、関連する継承は、Entity Framework が指定された が であるかどうかを認識しないことを意味するOrderedState
ため、データベースへの単一のトリップを実行して を含める方法がないように見えることOrderedState.Order
です。
だから私ができないことは次のようなものです:
statefulEntityRepository.Get().Where( x => x.Id == 1 ).Include( x => x.BasicStates ).Include( x.BasicStates.Order );
明らかに、それは実行されるコードではありませんが、問題が何であるかを示しています. Order は特定のサブタイプにのみ属しているBasicState
ため、何らかのキャストを使用している場合でも、EF はそれをプリロードしません。
投影を試みると、次のようなものが得られます。
statefulEntityRepository.Get().Select( x=> new {
StatefulEntity = x,
EntityLocation = ( from state in x.BaseStates where state is ReceivedState select state.EntityLocation )
}
しかし、プロジェクションによって返された匿名型から StatefulEntity に戻る方法を見つけて、コードの残りの部分がそれを処理できるようにする必要があることがわかりました。
私は基本クラスと継承者を次のように定義しようとしています:
public abstract class BaseState
{
public DateTime CreatedDate { get; set; }
public ICollection<StatefulEntity> StatefulEntities{get;set;}
public long EntitytLocationId { get; set; }
}
public abstract class LocationState : BaseState
{
[Column(name="EntityLocationId")]
public Location EntityLocation { get; set; }
}
などなどですが、そもそも TPH を使用するという基本的なポイントを破っているように見え、ジェネリック データ クラスに独自のオブジェクト モデルを転がしているような気がします。
編集:私はこれについてもう少し理解していると思います-その関係(つまり、 Location と LocationState の間の関係)の遠端に ForeignKey を設定しようとすると、 Order または Location の逆コレクションができるように見えますベース オブジェクトにないプロパティと対話しないため、上記のバージョンを使用する必要があります。これにより、EntityLocationId または OrderId を持たないケースを管理する方法に新しい問題が生じます。これらのフィールドを null 可能にすると、データベースの作成中に参照フィールドを null にできないというエラーが発生し、デフォルトでは、 Code First のフィールド。
Entity Framework で動作するこのタイプのモデルを表現するより良い方法を推奨できる人はいますか?