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

ASP.NET Core MVC:使用ViewModel获取详情功能失效问题

解决ASP.NET Core MVC中ViewModel详情页查询报错问题

问题背景

在ASP.NET Core MVC项目中,Index方法通过多表关联查询构造NodeIndexViewModel并成功渲染视图,但访问详情页时触发以下PostgreSQL错误:

PostgresException: 42P01: relation "NodeIndexViewModel" does not exist

错误的Details方法代码如下:

public async Task<IActionResult> Details(int? id)
{
    if (id == null || _context.NodeIndexViewModel == null)
    {
        return NotFound();
    }

    var nodeIndexViewModel = await _context.NodeIndexViewModel
                                           .FirstOrDefaultAsync(m => m.Id == id);

    if (nodeIndexViewModel == null)
    {
        return NotFound();
    }

    return View(nodeIndexViewModel);
}

问题原因

NodeIndexViewModel是视图模型(ViewModel),仅用于封装视图所需数据,并非EF Core映射的数据库实体,因此_context中不存在对应的NodeIndexViewModel集合。直接通过_context.NodeIndexViewModel查询时,EF Core会尝试在数据库中查找名为NodeIndexViewModel的表,而该表实际不存在,导致报错。

解决方案

需要像Index方法一样,通过多表关联查询构造NodeIndexViewModel实例,或者先查询对应的实体再映射为ViewModel。以下是修正后的Details方法:

public async Task<IActionResult> Details(int? id)
{
    if (id == null)
    {
        return NotFound();
    }

    var nodeDetail = await (from node in _context.Nodes
                           join bnbridge in _context.BundleNodes on node.Id equals bnbridge.NodeId into NodeBundleIDGroup
                           from ax in NodeBundleIDGroup.DefaultIfEmpty()
                           join bundle in _context.Bundles on ax.BundleId equals bundle.Id into NodeBundleGroup
                           from bx in NodeBundleGroup.DefaultIfEmpty()
                           join agreement in _context.Agreements on bx.AgreementId equals agreement.Id into agGroup
                           from cx in agGroup.DefaultIfEmpty()
                           join org in _context.Organizations on cx.OrgId equals org.Id into oGroup
                           from ex in oGroup.DefaultIfEmpty()
                           join conorg in _context.Organizations on node.OrgId equals conorg.Id into tGroup
                           from fx in tGroup.DefaultIfEmpty()
                           where node.Id == id
                           select new NodeIndexViewModel
                           {
                               Id = node.Id,
                               Name = node.Name,
                               AssignedOrg = fx.ShortName,
                               ContractingOrg = ex.ShortName,
                               Expiry = bx.EndUtc,
                               LastActive = node.ActiveDate,
                               NodeType = bx.NodeTypeID
                           }).FirstOrDefaultAsync();

    if (nodeDetail == null)
    {
        return NotFound();
    }

    return View(nodeDetail);
}

优化建议

如果多表关联逻辑重复,可以将其封装为一个可复用的方法,避免Index和Details方法中重复编写查询代码:

private IQueryable<NodeIndexViewModel> GetNodeIndexQuery()
{
    return from node in _context.Nodes
           join bnbridge in _context.BundleNodes on node.Id equals bnbridge.NodeId into NodeBundleIDGroup
           from ax in NodeBundleIDGroup.DefaultIfEmpty()
           join bundle in _context.Bundles on ax.BundleId equals bundle.Id into NodeBundleGroup
           from bx in NodeBundleGroup.DefaultIfEmpty()
           join agreement in _context.Agreements on bx.AgreementId equals agreement.Id into agGroup
           from cx in agGroup.DefaultIfEmpty()
           join org in _context.Organizations on cx.OrgId equals org.Id into oGroup
           from ex in oGroup.DefaultIfEmpty()
           join conorg in _context.Organizations on node.OrgId equals conorg.Id into tGroup
           from fx in tGroup.DefaultIfEmpty()
           select new NodeIndexViewModel
           {
               Id = node.Id,
               Name = node.Name,
               AssignedOrg = fx.ShortName,
               ContractingOrg = ex.ShortName,
               Expiry = bx.EndUtc,
               LastActive = node.ActiveDate,
               NodeType = bx.NodeTypeID
           };
}

然后在Index和Details方法中调用:

  • Index方法中替换原查询:var results = GetNodeIndexQuery();
  • Details方法中:var nodeDetail = await GetNodeIndexQuery().Where(n => n.Id == id).FirstOrDefaultAsync();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 10:25:35