ASP.NET Core中ViewModel分页功能失效,存在类型转换冲突问题
解决分页时的类型转换冲突问题
看起来你遇到的核心问题是查询返回的匿名类型和PaginatedList<Employee>期望的类型不匹配,咱们一步步拆解解决:
问题根源分析
你在控制器里构建的employeeList是一个匿名类型的集合:
var employeeList = (from e in _context.Employees join s in _context.Employees on e.Id equals s.SupervisorId select new { Employee = s, Supervisor = e.FullName });
但你尝试把这个匿名类型集合传给PaginatedList<Employee>.CreateAsync——它需要的是IQueryable<Employee>类型的数据源,自然会抛出类型转换错误。而且你的EmployeeListViewModel里还需要Supervisor字段,直接传Employee集合也没法把主管名字带过去。
解决方案:调整查询与分页类型适配
我们可以修改查询,直接投影到包含Employee和Supervisor的明确结构,同时让PaginatedList的泛型类型适配这个结构。
步骤1:新建DTO存储员工+主管信息
先创建一个简单的数据传输对象(DTO),用来封装员工和对应的主管姓名:
public class EmployeeWithSupervisorDto { public Employee Employee { get; set; } public string SupervisorName { get; set; } }
步骤2:修改控制器查询逻辑
把原本的匿名类型投影改成DTO类型:
var employeeList = (from e in _context.Employees join s in _context.Employees on e.Id equals s.SupervisorId select new EmployeeWithSupervisorDto { Employee = s, SupervisorName = e.FullName }); // 搜索逻辑保持不变 if (!String.IsNullOrEmpty(searchString)) { employeeList = employeeList.Where(e => e.Employee.LastName.Contains(searchString) || e.Employee.FirstName.Contains(searchString)); }
步骤3:更新ViewModel与分页调用
调整EmployeeListViewModel的结构,适配新的分页集合类型:
public class EmployeeListViewModel { public PaginatedList<EmployeeWithSupervisorDto> EmployeesWithSupervisor { get; set; } // 原有的单个Employee和Supervisor字段如果不需要可以移除,按需保留 }
然后修改控制器的返回逻辑:
int pageSize = 3; return View(new EmployeeListViewModel { EmployeesWithSupervisor = await PaginatedList<EmployeeWithSupervisorDto>.CreateAsync(employeeList.AsNoTracking(), pageNumber ?? 1, pageSize) });
步骤4:调整视图中的数据遍历
更新视图顶部的模型引用后,就可以同时获取员工和主管信息了:
@model MMSystem.ViewModels.EmployeeListViewModel @foreach (var item in Model.EmployeesWithSupervisor) { <div> <p>员工:@item.Employee.FirstName @item.Employee.LastName</p> <p>主管:@item.SupervisorName</p> </div> } <!-- 分页控件逻辑保持不变,PaginatedList的分页交互不受泛型类型影响 -->
简化方案(无需新建DTO)
如果你不想额外创建DTO类,可以给Employee类临时添加一个SupervisorName属性,直接投影到Employee对象上:
// 假设Employee类新增了SupervisorName属性 var employeeList = (from e in _context.Employees join s in _context.Employees on e.Id equals s.SupervisorId select new Employee { Id = s.Id, FirstName = s.FirstName, LastName = s.LastName, // 务必赋值所有需要用到的Employee属性 SupervisorName = e.FullName });
这种方式需要确保所有Employee的属性都被正确投影,否则EF可能会抛出实体跟踪相关的错误,所以更推荐第一种DTO的方案。
内容的提问来源于stack exchange,提问作者balance85
相关产品推荐
相关产品推荐

