EF Core中如何实现按条件关联不同实体的左连接查询
EF Core 条件左连接查询实现方案
前置准备
首先确保你的EF Core上下文与对应实体已正确定义,参考结构如下:
// 交易表实体 public class Transaction { public int Id { get; set; } public int OrderId { get; set; } /// <summary> /// 订单类型:0=销售单,1=采购单,可扩展 /// </summary> public int OrderType { get; set; } public decimal Amount { get; set; } } // 销售单实体 public class Sale { public int Id { get; set; } public string OrderNo { get; set; } // 其他销售单字段省略 } // 采购单实体 public class Purchase { public int Id { get; set; } public string OrderNo { get; set; } // 其他采购单字段省略 } // 数据库上下文 public class AppDbContext : DbContext { public DbSet<Transaction> Transactions { get; set; } public DbSet<Sale> Sales { get; set; } public DbSet<Purchase> Purchases { get; set; } // 上下文其他配置省略 }
具体查询写法
以下两种写法均可生成与你提供的原生SQL逻辑完全一致的语句,仅触发一次数据库查询,解决多次调用的性能问题。
方式1:查询语法(可读性更高)
var query = from ap in _dbContext.Transactions // 条件左连接销售表 join s in _dbContext.Sales on new { OrderId = ap.OrderId, Type = 0 } equals new { OrderId = s.Id, Type = 0 } into sGroup from s in sGroup.DefaultIfEmpty() // 条件左连接采购表 join p in _dbContext.Purchases on new { OrderId = ap.OrderId, Type = 1 } equals new { OrderId = p.Id, Type = 1 } into pGroup from p in pGroup.DefaultIfEmpty() select new { ap.Id, ap.OrderId, ap.OrderType, ap.Amount, // 空合并运算符会自动转换为SQL的COALESCE函数 OrderNo = s.OrderNo ?? p.OrderNo // 如需其他字段可自行补充 }; // 执行查询获取结果 var result = await query.ToListAsync();
方式2:方法语法
var result = await _dbContext.Transactions // 左连接销售表 .GroupJoin( _dbContext.Sales, ap => new { ap.OrderId, Type = 0 }, s => new { OrderId = s.Id, Type = 0 }, (ap, sGroup) => new { ap, Sale = sGroup.FirstOrDefault() } ) // 左连接采购表 .GroupJoin( _dbContext.Purchases, temp => new { temp.ap.OrderId, Type = 1 }, p => new { OrderId = p.Id, Type = 1 }, (temp, pGroup) => new { temp.ap, temp.Sale, Purchase = pGroup.FirstOrDefault() } ) // 映射结果 .Select(res => new { res.ap.Id, res.ap.OrderId, res.ap.OrderType, res.ap.Amount, OrderNo = res.Sale.OrderNo ?? res.Purchase.OrderNo }) .ToListAsync();
扩展说明
如果后续OrderType新增了其他取值,只需要按照上述格式新增对应表的左连接逻辑,同时在空合并运算的参数中加入对应表的字段即可兼容。
内容的提问来源于stack exchange,提问作者Hussain Murtaza
相关产品推荐
相关产品推荐

