EF Core查询报InvalidOperationException:LINQ表达式无法翻译问题如何解决
错误根本原因
该InvalidOperationException是EF Core无法将LINQ表达式翻译为合法SQL语句导致的,核心问题如下:
- 你在
Select投影步骤仅将数据库实体的FileName、FileContent字段映射到自定义的FileUploadModel,没有为Id字段赋值,也未建立FileUploadModel.Id和数据库表FileUploads的Id字段的关联,EF Core无法识别SingleAsync条件中x.Id对应的数据库字段,无法完成SQL翻译。 - 筛选逻辑写在投影操作之后,EF Core默认不会自动将自定义模型的属性筛选逻辑下推到数据库执行,异步查询场景下也不允许隐式将未翻译的逻辑放到内存中执行,因此直接抛出异常。
解决办法
推荐优先使用「先筛选后投影」的方案,性能最优,只会从数据库查询你需要的字段:
public async Task<IActionResult> OnGet() { var context = _dbFactory.CreateDbContext(); var file = await context.FileUploads // 先基于数据库原生实体做筛选,可正常翻译为SQL的WHERE条件 .Where(x => x.Id == Id) .Select(x => new FileUploadModel { FileName = x.FileName, FileContent = x.FileContent }) .SingleAsync(); return File(file.FileContent, FilesConst.DownloadsConst.ApplicationForceDownload, file.FileName); }
如果你有特殊需求必须先投影再筛选,可以先将投影结果加载到内存后再做筛选,该方案仅适合数据量小的场景:
public async Task<IActionResult> OnGet() { var context = _dbFactory.CreateDbContext(); // 先通过ToListAsync将所有投影结果加载到内存,后续筛选在内存中执行 var file = (await context.FileUploads.Select(x => new FileUploadModel { // 必须给Id属性赋值,内存筛选才能正常取到值 Id = x.Id, FileName = x.FileName, FileContent = x.FileContent }).ToListAsync()) .Single(x => x.Id == Id); return File(file.FileContent, FilesConst.DownloadsConst.ApplicationForceDownload, file.FileName); }
内容的提问来源于stack exchange,提问作者MarchalPT
相关产品推荐
相关产品推荐

