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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:33:44