1

これは、クラスとして説明されている、私が扱っている単純化されたテーブルのセットです。T4 テンプレートを使用して単純な POCO を作成しています。 質問を混乱させる可能性のあるすべてのクラスの必須ではないプロパティをすべて削除しました

public class MarketingPlan
{
  public guid MarketingPlanID { get; set; }
  public bool Disabled { get; set; }
  public virtual ICollection<MarketingPlanItem> MarketingPlanItems { get; set; }
}

public partial class MarketingPlanItem
{
    public System.Guid MarketingPlanItemID { get; set; }
    public System.Guid MarketingPlanID { get; set; }
    public System.Guid MarketingPlanItemTypeID { get; set; }
    public bool Disabled { get; set; }
    public Nullable<System.Guid> EmailTemplateID { get; set; }
    public virtual EmailTemplate EmailTemplate { get; set; }
    public virtual MarketingPlanItemType MarketingPlanItemType { get; set; }
}

public partial class EmailTemplate
{
    public System.Guid EmailTemplateID { get; set; }
}

public partial class MarketingPlanItemType
{
    public System.Guid MarketingPlanItemTypeID { get; set; }
}

作成しようとしている厳密に型指定された結果は、Entity Framework コンテキストに接続する必要はありません。これが私の解決策の試みです。

public MarketingPlan GetMarketingPlanWithItems(Guid marketingPlanID)
{
  var query = 
      this.Context
          .MarketingPlanItems
          .GroupJoin(this.Context.MarketingPlanItemTypes,
                     mpi => mpi.MarketingPlanItemTypeID,
                     mpit => mpit.MarketingPlanItemTypeID,
                     (mpi, mpit) =>
                     {
                       mpi.MarketingPlanItemType = mpit.FirstOrDefault();
                       return mpi;
                     })
          .GroupJoin(this.Context.EmailTemplates,
                     mpi => mpi.EmailTemplateID,
                     et => et.EmailTemplateID,
                     (mpi, et) =>
                     {
                       mpi.EmailTemplate = et.FirstOrDefault();
                       return mpi;
                     })
          .Where(mpi => mpi.Disabled == false);

  var result = 
      this.Context
          .MarketingPlans
          .GroupJoin(query,
                     mp => mp.MarketingPlanID,
                     mpi => mpi.MarketingPlanID,
                     (mp, mpi) =>
                     {
                       mp.MarketingPlanItems = mpi.ToList();
                       return mp;
                     })
          .Where(mp => mp.MarketingPlanID == marketingPlanID)
          .FirstOrDefault();

  return result;
}

GroupJoin次のエラーがスローされるため、実際の匿名関数を使用できないことに気付きました。

ステートメント本体を含むラムダ式は式ツリーに変換できません

この例では、このようにコーディングしました。これはnew、厳密に型指定されたオブジェクトの場合、すべてのフィールドにデータを入力する必要があると思われるためです。

最終結果は持つことです。でMarketingPlanMarketingPlanItemsないものだけが取り込まれ、EmailTemplate または Null によって取り込まれ、各 MarketingPlanItem にそれが取り込まれDisableます。このための sql は (おおまかに) 次のようになります。EmailTemplateMarketingPlanItemType

SELECT
  mp.*,
  mpi.*,
  mpit.*,
  et.*
FROM
  MarketingPlan mp
  LEFT JOIN MarketingPlanItem mpi 
    on mp.MarketingPlanID = mpi.MarketingPlanID 
  INNER JOIN MarketingPlanItemType mpit 
    on mpi.MarketingPlanItemTypeID = mpit.MarketingPlanItemTypeID
  LEFT JOIN EmailTemplate et
    on mpi.EmailTemplateID = et.EmailTemplateID

データベースに複数のリクエストを行うことなく、Lambda を使用して Entity Framework でこれを達成する方法はありますか?

更新 1

public MarketingPlan GetMarketingPlanWithItems(Guid marketingPlanID)
{
  MarketingPlan result = null;

  var query = this.Context.MarketingPlanItems
                          .Include("MarketingPlan")
                          .Include("MarketingPlanItemType")
                          .Include("EmailTemplate")
                          .Include("EmailTemplate.EmailTemplateCategory")
                          .Where(mp => !mp.Disabled
                                       && !mp.MarketingPlan.Disabled
                                       && mp.MarketingPlanID == marketingPlanID)
                          .ToList();

  var query2 = query.FirstOrDefault();

  if (query2 != null)
  {
    result = query2.MarketingPlan;
    result.MarketingPlanItems = query;
  }

  return result;
}

これにより、最終的に必要なものが返されました。

4

2 に答える 2

3

プランアイテムだけ返品できませんか?

そのような:

var items = this.Context.MarketingPlanItems
            .Where(x => !x.Disabled && !x.MarketingPlan.Disabled)

返される各アイテムには、すでに関連付けられた電子メールテンプレートがあります。item.EmailTemplate手動で結合する必要はなく、そのまま使用してください。

その結果、実際に新しいエンティティを作成しなくても、有効なアイテムで各プランを表す、または独自のカスタムのitem.MarketingPlan.MarketingPlanIDようなもので最終的にグループ化できます。Dictionary<MarketingPlan, IList<MarketingPlanItem>>Type

ORMを利用して関係を解決してみませんか?SELECT N + 1の問題に注意し、EFが関連するすべてのエンティティをフェッチしていることを確認してください。使用など:

this.Context.MarketingPlanItems
    .Include(i => i.MarketingPlan)
    .Include(i => i.EmailTemplate)

型に拡張メソッドを記述してMarketingPlan、有効なアイテムを返す式を返し、Linqでも使用できます。

于 2012-07-05T17:38:03.063 に答える
1

私が間違っていない場合は、MarketingPlansの関連するサブアイテムをロードする必要があります。

Include()を使ってみませんか?次のようなものを使用します。

this.Context.MarketingPlans.Include("MarketingPlanItems.EmailTemplates")
于 2012-07-05T17:37:19.390 に答える