簡體   English   中英

具有多個連接的Lambda返回強類型對象

[英]Lambda with Multiple Joins returning strongly typed objects

這是我正在使用的一組簡化的表,描述為類。 我正在使用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使用真正的匿名函數,因為它會拋出以下錯誤:

具有語句主體的lambda表達式無法轉換為表達式樹

我在這個例子中用這種方式編碼,因為如果我new一個強類型對象,我相信我必須填充每個我不想做的字段。

最終的結果是; 一個MarketingPlan ,它的MarketingPlanItems只填充了非Disable ,它的EmailTemplate要么是由EmailTemplate填充的,要么是Null,每個MarketingPlanItem都填充了它的MarketingPlanItemType 這個sql可能看起來像(粗略地):

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的實體框架中完成此操作而不對數據庫執行多個請求?

更新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;
}

這最終歸還了我需要的東西。

你不能只返回計划項目嗎?

如:

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一起使用。

如果我沒弄錯,你想為MarketingPlans加載相關的子項。

你為什么不使用Include()? 使用這樣的東西:

this.Context.MarketingPlans.Include("MarketingPlanItems.EmailTemplates")

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM