gpt4 book ai didi

c# - 具有多个连接的 Lambda 返回强类型对象

转载 作者:太空宇宙 更新时间:2023-11-03 21:58:10 26 4
gpt4 key购买 nike

这是我正在使用的一组简化表,描述为类。我正在使用 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 中使用真正的匿名函数,因为它会抛出以下错误:

A lambda expression with a statement body cannot be converted to an expression tree

我在这个例子中是这样编码的,因为如果我新建一个强类型对象,我相信我必须填充每个我不想做的字段。

最终的结果是;一个 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 在 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;
}

这最终返回了我需要的东西。

最佳答案

你不能只退回计划项目吗?

如:

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

关于c# - 具有多个连接的 Lambda 返回强类型对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11348877/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com