如何编写Entity Framework扩展方法从一对多模型获取ViewModel列表
实现Entity Framework扩展方法获取一对多关系的ViewModel列表
首先,咱们得先定义对应的ViewModel,把实体中需要展示的字段抽出来——这是领域模型和视图模型分离的最佳实践,避免直接返回实体类暴露不必要的信息:
public class ProjectViewModel { public Guid Id { get; set; } public string ProjectName { get; set; } // 只返回需要展示的分类名称,不用返回整个Category对象 public string CategoryName { get; set; } }
接下来就是写EF的扩展方法了,咱们可以扩展IQueryable<Project>,这样就能在查询Project的时候直接链式调用这个方法,自动关联Category并转成ViewModel:
using Microsoft.EntityFrameworkCore; public static class ProjectQueryExtensions { // 扩展方法:第一个参数用this标记要扩展的IQueryable<Project>类型 public static IQueryable<ProjectViewModel> ToProjectViewModel(this IQueryable<Project> projects) { return projects // 关联Category表,避免*N+1查询问题*,确保一次性拉取关联数据 .Include(p => p.Category) // 投影到ViewModel .Select(p => new ProjectViewModel { Id = p.Id, ProjectName = p.ProjectName, // 处理Category为null的情况(因为CategoryId是可空字段) CategoryName = p.Category?.CategoryName ?? "未分类" }); } }
然后在控制器里就可以轻松复用这个扩展方法了,假设你已经通过依赖注入拿到了DbContext:
[ApiController] [Route("api/[controller]")] public class ProjectsController : ControllerBase { private readonly YourDbContext _dbContext; public ProjectsController(YourDbContext dbContext) { _dbContext = dbContext; } [HttpGet] public async Task<ActionResult<IEnumerable<ProjectViewModel>>> GetProjects() { // 直接链式调用扩展方法,代码简洁易读 var projectViewModels = await _dbContext.Projects .ToProjectViewModel() .ToListAsync(); return Ok(projectViewModels); } }
这里还有几个小细节要注意:
- 必须用
Include关联Category,否则EF会触发多次查询,影响性能 - 因为
CategoryId是可空类型,映射CategoryName时一定要处理null场景,避免空引用异常 - 扩展方法必须放在静态类中,方法本身也得是静态的,第一个参数的
this关键字是扩展方法的标识
内容的提问来源于stack exchange,提问作者J Smith
相关产品推荐
相关产品推荐

