Entity Framework复杂嵌套查询转换与ViewModel视图表创建技术问题
在Entity Framework中处理复杂嵌套查询并绑定ViewModel到视图
看起来你已经有了验证过的MySQL查询语句,现在需要解决的是把这个复杂查询转换成EF能处理的形式,最终把数据绑定到ViewModel并在视图里生成表格。我给你分两种方案来解决,你可以根据自己的需求选择:
方案一:直接执行原生MySQL查询(最稳妥,适合复杂场景)
既然你的原生SQL已经能得到正确结果,直接让EF执行这个查询然后映射到你的ApplicationContentViewModel是最直接的方式,避免EF转换复杂查询时出问题。
步骤1:创建匹配查询结果的DTO(可选但更清晰)
先定义一个和查询结果字段对应的DTO,方便接收数据:
public class AppContentDelegationDto { public string APP_UID { get; set; } public string ProjectTitle { get; set; } // 对应你查询中PRO_TITLE的CON_VALUE public string DelegateUid { get; set; } // 对应app_delegation的DELEGATE_UID // 其他需要从三个表获取的字段都在这里定义 }
步骤2:在EF中执行原生SQL并映射到ViewModel
在你的DbContext里执行原生查询,再把DTO转换成目标ViewModel:
// 把你验证过的完整SQL语句放这里 var rawSql = @"SELECT a.APP_UID, (SELECT CON_VALUE FROM content WHERE CON_CATEGORY = 'PRO_TITLE' AND APP_UID = a.APP_UID) AS ProjectTitle, d.DELEGATE_UID AS DelegateUid FROM application a LEFT JOIN app_delegation d ON a.APP_UID = d.APP_UID"; // 执行原生SQL获取DTO列表 var dtoList = _dbContext.Set<AppContentDelegationDto>() .FromSqlRaw(rawSql) .ToList(); // 转换为你的ApplicationContentViewModel var viewModelList = dtoList.Select(dto => new ApplicationContentViewModel { application = new BPMSPARS.Models.MySql.Application { APP_UID = dto.APP_UID }, content = new BPMSPARS.Models.MySql.Content { CON_VALUE = dto.ProjectTitle, CON_CATEGORY = "PRO_TITLE", APP_UID = dto.APP_UID }, app_delegation = new BPMSPARS.Models.MySql.AppDelegation { APP_UID = dto.APP_UID, DELEGATE_UID = dto.DelegateUid } }).ToList();
方案二:将嵌套查询转换为LINQ查询(纯EF风格)
如果想尽量用EF的LINQ语法而非原生SQL,可以把你的嵌套查询转换成LINQ表达式:
var viewModelList = (from app in _dbContext.application // 左连接app_delegation表 join delegation in _dbContext.app_delegation on app.APP_UID equals delegation.APP_UID into delegationGroup from delegation in delegationGroup.DefaultIfEmpty() select new ApplicationContentViewModel { application = app, // 对应你MySQL里的嵌套子查询,获取PRO_TITLE对应的content content = _dbContext.content.FirstOrDefault(c => c.CON_CATEGORY == "PRO_TITLE" && c.APP_UID == app.APP_UID), app_delegation = delegation }).ToList();
⚠️ 注意:如果你的查询逻辑特别复杂,EF的LINQ提供器可能无法生成正确的SQL语句,这时候方案一的原生SQL方式会更可靠。另外,这种写法可能会触发N+1查询问题(每条application单独查一次content),如果数据量较大,建议用JOIN代替子查询优化性能。
视图中生成表格
拿到viewModelList后,在Razor视图里循环生成表格即可:
<table class="table table-striped"> <thead> <tr> <th>应用UID</th> <th>项目标题</th> <th>委托UID</th> <!-- 其他需要展示的列 --> </tr> </thead> <tbody> @foreach (var vm in Model) { <tr> <td>@vm.application.APP_UID</td> <td>@vm.content?.CON_VALUE</td> <!-- 用?.处理content为空的情况 --> <td>@vm.app_delegation?.DELEGATE_UID</td> <!-- 处理委托记录为空的情况 --> <!-- 其他列 --> </tr> } </tbody> </table>
小提示优化
如果你的嵌套查询可以改成JOIN形式(性能更好),可以把原生SQL调整为:
SELECT a.APP_UID, c.CON_VALUE AS ProjectTitle, d.DELEGATE_UID AS DelegateUid FROM application a LEFT JOIN content c ON a.APP_UID = c.APP_UID AND c.CON_CATEGORY = 'PRO_TITLE' LEFT JOIN app_delegation d ON a.APP_UID = d.APP_UID
这种JOIN的方式比嵌套子查询性能更优,EF也更容易处理。
内容的提问来源于stack exchange,提问作者Lili.brh
相关产品推荐
相关产品推荐

