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

一对多关系场景下,如何在ViewModel中获取关联模型数据?

关于在ViewModel中展示关联分类名称的最佳实践

我知道这是常见问题,但仍困惑于在ViewModel中获取关联模型数据的最佳实践。我希望在视图中展示Review或Comment数据时附带Category名称,但当前ViewModel中仅存在CategoryId。请问是否应在ViewModel中添加Category列表,再在视图中通过CategoryId查找对应分类?还是有更优的解决方案?


模型定义

Review模型

public class Review
{
    public int Id { get; set; }
    public string Author { get; set; }
    [MaxLength(500)]
    public string Body { get; set; }
    public int Rating { get; set; }
    public bool IsBuyer { get; set; }

    public int CategoryId { get; set; }
    public Category Category { get; set; }
}

Comment模型

public class Comment
{
    public int Id { get; set; }
    public string Author { get; set; }
    [MaxLength(500)]
    public string Body { get; set; }

    public int CategoryId { get; set; }
    public Category Category { get; set; }
}

Category模型

public class Category 
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Type { get; set; }
    public string Description { get; set; }

    public List<Comment> Comments { get; set; }
    public List<Review> Reviews { get; set; }
}

RevComVm视图模型

public class RevComVm
{
    public Review Review { get; set; }
    public Comment Comment { get; set; }

    public List<Review> Reviews { get; set; }
    public List<Comment> Comments { get; set; }
}

解决方案

1. 直接预加载关联实体(最简便)

如果使用EF Core,查询时通过Include方法预加载关联的Category数据,这样ViewModel中的Review/Comment对象就能直接访问分类名称:

var vm = new RevComVm
{
    Reviews = _dbContext.Reviews.Include(r => r.Category).ToList(),
    Comments = _dbContext.Comments.Include(c => c.Category).ToList()
};

视图中直接使用:

@foreach (var review in Model.Reviews)
{
    <div>@review.Author - @review.Category.Name</div>
}

2. 创建扁平化专用ViewModel(推荐最佳实践)

为视图创建仅包含所需字段的ViewModel,避免传递完整领域模型,直接嵌入分类名称:

// 列表项专用ViewModel
public class ReviewListItemVm
{
    public int Id { get; set; }
    public string Author { get; set; }
    public string Body { get; set; }
    public int Rating { get; set; }
    public bool IsBuyer { get; set; }
    public string CategoryName { get; set; }
}

public class CommentListItemVm
{
    public int Id { get; set; }
    public string Author { get; set; }
    public string Body { get; set; }
    public string CategoryName { get; set; }
}

// 更新主ViewModel
public class RevComVm
{
    public List<ReviewListItemVm> Reviews { get; set; }
    public List<CommentListItemVm> Comments { get; set; }
}

查询时投影到扁平ViewModel:

var vm = new RevComVm
{
    Reviews = _dbContext.Reviews
        .Select(r => new ReviewListItemVm
        {
            Id = r.Id,
            Author = r.Author,
            Body = r.Body,
            Rating = r.Rating,
            IsBuyer = r.IsBuyer,
            CategoryName = r.Category.Name
        }).ToList(),
    Comments = _dbContext.Comments
        .Select(c => new CommentListItemVm
        {
            Id = c.Id,
            Author = c.Author,
            Body = c.Body,
            CategoryName = c.Category.Name
        }).ToList()
};

这种方式更符合单一职责原则,只传递视图需要的数据,减少冗余。

3. 分类字典映射(适合稳定分类场景)

如果不想修改现有ViewModel,可以添加分类ID到名称的字典映射,视图中通过ID查找:

// 更新ViewModel
public class RevComVm
{
    public List<Review> Reviews { get; set; }
    public List<Comment> Comments { get; set; }
    public Dictionary<int, string> CategoryNameMap { get; set; }
}

查询时构建字典:

var categoryMap = _dbContext.Categories.ToDictionary(c => c.Id, c => c.Name);
var vm = new RevComVm
{
    Reviews = _dbContext.Reviews.ToList(),
    Comments = _dbContext.Comments.ToList(),
    CategoryNameMap = categoryMap
};

视图中使用(需处理ID不存在的情况):

@foreach (var comment in Model.Comments)
{
    <div>@comment.Author - @(Model.CategoryNameMap.ContainsKey(comment.CategoryId) ? Model.CategoryNameMap[comment.CategoryId] : "未知分类")</div>
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 01:06:25