[英]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.