ASP.NET Core 5.0 Linq外连接需求:获取所有含/无Equipment的Movement
获取所有Movements记录(包含无关联Equipment的条目)
你的当前代码使用的是内连接,只有当Movements在MovementEquips和Equipment中都有匹配记录时才会被查询出来,因此过滤掉了没有关联器材的动作(比如Pushup)。要实现需求的外连接效果,需要修改Linq查询的连接方式:
方法一:显式左外连接
使用Linq的左外连接语法,通过join ... into ...和DefaultIfEmpty()保留所有Movements,即使没有对应的关联记录:
Movements = ( from mvmt in applicationDbContext.Movements // 左外连接MovementEquips join mvmteq in applicationDbContext.MovementEquips on mvmt.MvmtId equals mvmteq.MvmtId into mvmtEqGroup from mvmteq in mvmtEqGroup.DefaultIfEmpty() // 左外连接Equipment(处理mvmteq为null的情况) join equip in applicationDbContext.Equipment on mvmteq?.EquipId equals equip.EquipId into equipGroup from equip in equipGroup.DefaultIfEmpty() orderby mvmt.MvmtId select new Movement { MvmtId = mvmt.MvmtId, MvmtDescr = mvmt.MvmtDescr }) .Distinct() // 去重:单个Movement关联多个Equipment时会产生重复记录 .ToList();
方法二:使用EF导航属性(更简洁)
如果你的EF实体模型中已经配置了导航属性(比如Movement类包含ICollection<MovementEquip> MovementEquips,MovementEquip类包含Equipment导航属性),可以直接用Include和ThenInclude,EF会自动生成左外连接的SQL:
Movements = applicationDbContext.Movements .Include(m => m.MovementEquips) .ThenInclude(me => me.Equipment) .OrderBy(m => m.MvmtId) .Select(m => new Movement { MvmtId = m.MvmtId, MvmtDescr = m.MvmtDescr }) .ToList();
关键说明
- 左外连接会保留左表(Movements)的所有记录,右表无匹配时返回
null - 当一个Movement关联多个Equipment时,左外连接会生成多条重复的Movement记录,因此方法一中需要用
Distinct()去重;方法二中基于导航属性的查询不会产生重复,因为是直接基于实体集合处理
内容的提问来源于stack exchange,提问作者Todd Wunsch
相关产品推荐
相关产品推荐

