0

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_Id2 つOrder_Idsを作成しました。OrderedStateDispatchedState

そのほとんど半分が解決されたので、私はこの質問をするように導く別の問題にぶつかりました:

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 で動作するこのタイプのモデルを表現するより良い方法を推奨できる人はいますか?

4

0 に答える 0