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

LINQ查询初始化ViewModel独立集合属性运行时报空如何解决

错误根因

你报错的核心原因是:将_db.Machinery.ToList()这类数据库查询操作写在了EF的IQueryable投影逻辑中,EF会尝试将这部分逻辑翻译为SQL语句执行,但数据库层面无法完成这种“给每条查询结果附加全量其他表数据”的操作,要么翻译直接失败抛出异常,要么每条结果都触发一次全表查询,引发性能问题和空引用异常。


方案1:保持现有List<DayTaskListViewModel>结构不变

如果你的业务确实需要每个DayTaskListViewModel实例都携带全量的两个集合,按以下步骤修改:
先提前把两个全量集合查询到内存,再给已查询出的列表批量赋值:

// 第一步:提前查询全局全量集合,仅执行1次数据库查询
var allMachinery = _db.Machinery.ToList();
var allCleaning = _db.Cleaning.ToList();

// 第二步:执行原有任务查询,不涉及两个集合的赋值
var model = (from a in _db.WorkTask.Where(y => y.TaskDate.Date == querytodaysDate.Date && y.IsActive == true && (y.IsPrivateUserName == null || y.IsPrivateUserName == currUserName))
              join b in _db.WorkTaskLog.Where(x => (x.UserName == currUserName || x.UserName == null) && x.IsActive == true && x.StateStatusId < 4) on a.Id equals b.WorkTaskId into joinedT
              from c in joinedT.DefaultIfEmpty()
              select new DayTaskListViewModel
              {
                  Id = a.Id,
                  DateFormatted = a.DateFormatted,
                  HasRegistrations = a.HasRegistrations,
                  HasStartedRegistrations = a.HasStartedRegistrations,
                  ItemName = a.ItemName,
                  WorkTypeName = a.WorkTypeName,
                  Description = a.Description,
                  IsActive = c.IsActive ? c.IsActive : false,
                  UserName = c.UserName ?? String.Empty,
                  StateStatus = c.StateStatus ?? "Klar",
                  WeekNumber = (int)currWeekNo,
                  YearNumber = (int)currYearNo,
                  Msg = "",
                  TodaysDate = (DateTime)todaysDate,
                  SignInUserName = currUserName,
                  LocationName = a.LocationName,
                  UnitCode = a.UnitCode
              }).ToList();

// 第三步:遍历内存列表,批量赋值集合属性
foreach (var taskItem in model)
{
    taskItem.machineryList = allMachinery;
    taskItem.cleaningList = allCleaning;
}

方案2:参考现有正常逻辑优化结构(更推荐)

你另一个控制器的写法逻辑是将主列表和全局集合拆分到外层ViewModel中,避免每条数据冗余存储相同的全量集合,性能更高,实现方式如下:

第一步:新增外层容器ViewModel

public class DayTaskListPageViewModel
{
    // 原有的任务列表
    public List<DayTaskListViewModel> TaskList { get; set; }
    // 全局独立集合
    public IEnumerable<Machinery> machineryList { get; set; }
    public IEnumerable<Cleaning> cleaningList { get; set; }
}

第二步:可选优化

如果不需要每个任务条目单独带集合,可以把DayTaskListViewModel里的machineryList和cleaningList属性删掉,减少冗余。

第三步:构造模型

// 查询任务列表
var taskList = (from a in _db.WorkTask.Where(y => y.TaskDate.Date == querytodaysDate.Date && y.IsActive == true && (y.IsPrivateUserName == null || y.IsPrivateUserName == currUserName))
              join b in _db.WorkTaskLog.Where(x => (x.UserName == currUserName || x.UserName == null) && x.IsActive == true && x.StateStatusId < 4) on a.Id equals b.WorkTaskId into joinedT
              from c in joinedT.DefaultIfEmpty()
              select new DayTaskListViewModel
              {
                  // 原有属性赋值不变,省略重复代码
                  Id = a.Id,
                  // ...其余属性和之前一致
              }).ToList();

// 构造外层模型,和你正常运行的写法逻辑完全一致
var model = new DayTaskListPageViewModel
{
    TaskList = taskList,
    machineryList = await _db.Machinery.ToListAsync(),
    cleaningList = await _db.Cleaning.ToListAsync()
};

第四步:视图适配

将视图绑定的模型类型改为DayTaskListPageViewModel,遍历Model.TaskList获取任务条目,直接通过Model.machineryList和Model.cleaningList调用全局集合即可。


内容的提问来源于stack exchange,提问作者René Wester

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 18:54:03