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

如何将带左连接子查询的SQL Server语句转换为LINQ?

原SQL转LINQ实现方案

先拆解原SQL逻辑

原SQL核心是:UserApplicationAccess与MasterApplication内连,再左连一个由ApplicationRole、MasterApplication、UserRole关联而成的子查询,最后对左连后的空字段替换默认值。


实现步骤1:先定义子查询(对应原SQL的x子查询)

var subQuery = from a in context.ApplicationRole.AsNoTracking()
               join m in context.MasterApplication.AsNoTracking() on a.ApplicationId equals m.Id
               join u in context.UserRole.AsNoTracking() on a.Id equals u.RoleId
               select new 
               {
                   a.Id,
                   a.Code,
                   a.Name,
                   AppId = m.Id,
                   u.UserCode
               };

实现步骤2:主查询+左连接逻辑

用LINQ的join ... into ...配合DefaultIfEmpty()实现SQL的LEFT JOIN,再用??处理空值替换:

// 替换为实际的用户编码参数
var targetUserCode = usercode;

var result = from ua in context.UserApplicationAccess.AsNoTracking()
             // 内连MasterApplication
             join ma in context.MasterApplication.AsNoTracking() on ua.ApplicationID equals ma.Id
             // 左连子查询,多条件连接用匿名类型匹配
             join x in subQuery 
             on new { ua.Usercode, ua.ApplicationID } equals new { x.UserCode, x.AppId } 
             into leftJoinedData
             // 左连的核心:DefaultIfEmpty()表示允许左连结果为空
             from x in leftJoinedData.DefaultIfEmpty()
             // 映射到DTO,空值替换默认值
             select new ApplicationRoleDTO2
             {
                 Id = x?.Id ?? 0,
                 Code = x?.Code ?? "DEFAULT",
                 Name = x?.Name ?? "DEFAULT"
             };

List<ApplicationRoleDTO2> UserRoles = result.ToList();

简化写法(子查询嵌入主查询)

如果不想单独定义子查询,也可以直接把逻辑嵌入主查询:

var targetUserCode = usercode;

var result = from ua in context.UserApplicationAccess.AsNoTracking()
             join ma in context.MasterApplication.AsNoTracking() on ua.ApplicationID equals ma.Id
             join x in (
                 from a in context.ApplicationRole.AsNoTracking()
                 join m in context.MasterApplication.AsNoTracking() on a.ApplicationId equals m.Id
                 join u in context.UserRole.AsNoTracking() on a.Id equals u.RoleId
                 select new 
                 {
                     a.Id,
                     a.Code,
                     a.Name,
                     AppId = m.Id,
                     u.UserCode
                 }) 
             on new { ua.Usercode, ua.ApplicationID } equals new { x.UserCode, x.AppId } into leftJoinedData
             from x in leftJoinedData.DefaultIfEmpty()
             select new ApplicationRoleDTO2
             {
                 Id = x?.Id ?? 0,
                 Code = x?.Code ?? "DEFAULT",
                 Name = x?.Name ?? "DEFAULT"
             };

List<ApplicationRoleDTO2> UserRoles = result.ToList();

关键注意点

  • LINQ实现LEFT JOIN的核心是join ... into ... + from ... DefaultIfEmpty(),对应SQL的LEFT JOIN逻辑
  • 多条件连接时,必须用匿名类型匹配字段,且两边的字段名、数据类型要完全一致
  • C#的??运算符等价于SQL的ISNULL,用来处理空值替换默认值
  • 保留AsNoTracking()可以避免EF跟踪实体,提升查询性能,和你原代码的思路一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 16:01:07