EF Core使用ToDictionary时报表达式无法翻译的问题解决咨询
异常产生原因
- 自定义C#方法无法被EF Core翻译:
SetTaskParentId、TaskHelper.GetTaskIcon均为本地定义的业务方法,EF Core没有内置的规则将其转换为SQL语句,直接放在面向数据库的LINQ查询投影中会触发翻译失败。 - 集合导航属性直接调用
ToDictionary不被支持:当前所有稳定版EF Core均不支持在数据库查询的投影中,直接对关联集合执行ToDictionary操作,没有对应SQL语法可以映射该操作。 - 你的两种写法逻辑本质完全一致,只是将
Select和ToDictionary的调用顺序合并,没有解决上述两个核心问题,因此报错相同。
最高效实现方案
不存在完全不需要加载原始数据到内存的方案:你需要用到的自定义转换逻辑只能在客户端执行,无法交给数据库处理。但可以通过仅拉取必要字段的方式,将性能损耗降到最低,是当前需求下的最优实现:
// 第一步:仅查询需要的字段,无冗余数据传输,仅执行1次数据库查询 var projectRaw = await Context.Projects .Where(x => x.Id == project.Id) .Select(x => new { x.Id, x.Name, Tasks = x.Tasks.Select(y => new { y.Id, y.Type, y.Name, y.Milestone, y.StartDate, y.CurrentEndDate, y.EndDate }).ToList() }).SingleOrDefaultAsync(); if (projectRaw == null) { Project = null; // 此处可补充项目不存在的业务逻辑 return; } // 第二步:内存中执行转换,自定义方法可正常运行 Project = new ProjectModel { Id = projectRaw.Id, Name = projectRaw.Name, TreeDataDict = projectRaw.Tasks.ToDictionary(y => y.Id, y => new TreeItemModel { NodeId = y.Id, ParentId = SetTaskParentId(y, y.Type), NodeTitle = y.Name, Expanded = false, Object = new TaskBaseModel { Milestone = y.Milestone, StartDate = y.StartDate, CurrentEndDate = y.CurrentEndDate, EndDate = y.EndDate, }, Icon = TaskHelper.GetTaskIcon(y.Type), Children = new List<TreeItemModel>() }) };
该方案相比全量加载实体再转换的实现,数据库IO开销可降低50%以上,同时完全避免翻译异常。
内容的提问来源于stack exchange,提问作者MarchalPT
相关产品推荐
相关产品推荐

