You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EF Core LINQ查询采购订单时如何加载关联公司主联系人邮箱

实体关联与需求说明

涉及3个存在关联关系的业务实体:

  • PurchaseOrder:属性包含Id、ProjectId、Source、CompanyId等
  • Company:属性包含Id、Name等
  • Contacts:属性包含Id、CompanyId、Email、AutoEM等

关联规则:

单个PurchaseOrder关联1个Company,单个Company可关联1个或多个Contacts,公司主联系人/默认联系人满足判断条件 AutoEM == true。

目标是通过LINQ查询指定ProjectId对应的PurchaseOrder集合,每条结果需要附带关联公司名称、该公司主联系人邮箱。
当前已完成PurchaseOrder关联Company的基础查询,代码如下:

pos = context.PurchaseOrder
             .Where(p => p.ProjectId == Int32.Parse(id))
             .Include(p => p.company)
             .ToList();

以下提供两种可直接落地的实现方案。


实现方案

方案1:过滤Include写法(EF Core 5.0+ 支持)

如果你的项目使用EF Core 5.0及以上版本,可以直接用ThenInclude搭配集合过滤条件,EF在生成查询时会自动仅加载满足AutoEM == true的联系人记录,不需要额外写内存过滤逻辑:

pos = context.PurchaseOrder
             .Where(p => p.ProjectId == Int32.Parse(id))
             .Include(p => p.company)
             .ThenInclude(c => c.Contacts.Where(co => co.AutoEM == true))
             .ToList();

查询完成后,主联系人邮箱可以直接通过 po.company.Contacts.FirstOrDefault()?.Email 取值,因为已经做了前置过滤,Contacts集合中最多只会存在匹配的主联系人数据。

方案2:投影查询(全EF版本兼容,性能更高)

如果使用的EF版本不支持过滤Include,或者不需要加载完整实体、仅需要指定字段,推荐用Select投影查询,该写法生成的SQL只会查询实际用到的字段,不会加载冗余数据,执行效率更高。
如果需要强类型返回结果,可以先定义传输对象:

public class PurchaseOrderDTO
{
    // 按需填写PurchaseOrder本身需要返回的字段
    public int Id { get; set; }
    public int ProjectId { get; set; }
    public string Source { get; set; }
    public int CompanyId { get; set; }
    // 要求附带的关联字段
    public string CompanyName { get; set; }
    public string PrimaryContactEmail { get; set; }
}

查询代码如下:

var pos = context.PurchaseOrder
             .Where(p => p.ProjectId == Int32.Parse(id))
             .Select(p => new PurchaseOrderDTO
             {
                 Id = p.Id,
                 ProjectId = p.ProjectId,
                 Source = p.Source,
                 CompanyId = p.CompanyId,
                 CompanyName = p.company.Name,
                 PrimaryContactEmail = p.company.Contacts
                                             .Where(co => co.AutoEM == true)
                                             .Select(co => co.Email)
                                             .FirstOrDefault()
             })
             .ToList();

如果不需要强类型,也可以直接投影到匿名对象使用。上述写法已经做了空值兼容,即使公司未设置主联系人,也不会抛出空引用异常,主联系人邮箱会返回null。


内容的提问来源于stack exchange,提问作者MichaelW

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 08:31:01