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
相关产品推荐
相关产品推荐

