一对多关系场景下,如何在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
相关产品推荐
相关产品推荐

