12

EF では、関連するエンティティを積極的に読み込むのは簡単です。

しかし、table-per-type モデルを使用してデータをロードするときに、継承されたエンティティを含めることが困難です。

これは私のモデルです:

エンティティ:

  • ArticleBase(基本物品エンティティ)
    • ArticleSpecial(から継承ArticleBase)
  • UserBase(ベース ユーザー エンティティ)
    • UserSpecial(から継承UserBase)
  • Image

関係は画像に示されているとおりです (多くの列を省略しています)。 代替テキスト

実際には、別のアプリケーションで使用されているUserSpecialため、私のユーザーは常にタイプであり、資格情報を共有できます。UserBaseそれが、私が 2 つの別々のテーブルを持っている唯一の理由です。UserBase他のアプリが壊れる可能性があるため、テーブルの形状を変更することはできません。

質問

両方が(関係を定義する) タイプになるように、ArticleSpecial両方CreatedByEditedByセットをロードするにはどうすればよいでしょうか?UserSpecialImage


私は(失敗しましたが)これらのオプションを試しました:

1. ラムダ式の使用:

context.ArticleBases
    .OfType<ArticleSpecial>()
    .Include("UserCreated.Image")
    .Include("UserEdited.Image");

この場合の問題は、 と の両方CreatedByEditedByに関連していて、ナビゲーションUserBaseを定義していないことです。したがって、これら2つを次のようImageにキャストする必要があります。UserSpecial

context.ArticleBases
    .OfType<ArticleSpecial>()
    .Include("UserCreated<UserSpecial>.Image")
    .Include("UserEdited<UserSpecial>.Image");

もちろん、ジェネリックを使用しても機能しInclude("UserCreated<UserSpecial>.Image")ません。

2. LINQ クエリを使用してみました

var results = from articleSpecial in ctx.ArticleBase.OfType<ArticleSpecial>()
                  join created in ctx.UserBase.OfType<UserSpecial>().Include("Image")
                  on articleSpecial.UserCreated.Id equals created.Id
                  join edited in ctx.UserBase.OfType<UserSpecial>().Include("Image")
                  on articleSpecial.UserEdited.Id equals edited.Id   
              select articleSpecial;

この場合ArticleSpecial、関連するプロパティが設定されていないオブジェクト インスタンスのみを取得しています。どういうわけかそれらを選択する必要があることは知っていますが、方法がわかりませんか?

私のLINQの選択部分は、次のように変更できます

select new { articleSpecial, articleSpecial.UserCreated, articleSpecial.UserEdited };

しかし、画像はまだ私のコンテキストにロードされていません。この場合の私のジョインは、articleSpecial の結果を除外するためにほとんど使用されていませんが、エンティティをコンテキストにロードしません (私はそう思います)。

4

1 に答える 1

3

これは、Entity Framework (1.0) の現在のバージョンの制限のようです。この関連する SO の質問を見てください。

あなたの場合、関連するUserCreatedおよびUserEditedプロパティをプロジェクションに含めることが正しい解決策です。ただし、 UserSpecialオブジェクトのImageプロパティも設定する場合は、それも含める必要があります。

var results = from articleSpecial in ctx.ArticleBase.OfType<ArticleSpecial>()
              select new
              {
                  articleSpecial,
                  articleSpecial.UserCreated,
                  ((UserSpecial)articleSpecial.UserCreated).Image,
                  articleSpecial.UserEdited,
                  ((UserSpecial)articleSpecial.UserEdited).Image
              };

もちろん、このクエリは、すべての ArticleSpecial エンティティが常に UserSpecial エンティティを参照するという前提に基づいて構築されています。そうでない場合、キャストは失敗します。
この仮定が常に正しいとは限らない場合は、LINQ 拡張メソッドと複数行のラムダ関数を使用して同じクエリを表現し、安全なキャストを実行できます。

var results = ctx.ArticleBase
                 .OfType<ArticleSpecial>()
                 .AsEnumerable()
                 .Select(a =>
                  {
                      var userCreated = a.UserCreated as UserSpecial;

                      if (userCreated != null)
                      {
                          var image = userCreated.Image;
                      }

                      var userEdited = a.UserEdited as UserSpecial;

                      if (userEdited != null)
                      {
                          var image = userEdited.Image;
                      }

                      return a;
                  });

後者の例では、結果にUserSpecialおよびImageエンティティを含める必要もありません。代わりに、プロジェクション フェーズ中にArticleSpecialエンティティのナビゲーション プロパティにアクセスするだけで、 Entity Framework に関連オブジェクトを強制的にロードさせることができます。

于 2010-03-30T19:59:31.243 に答える