如何改写EF Core的Where子句以避免LINQ表达式转换异常
解决方案
EF Core无法将你原代码中的内存集合操作或自定义对象比较翻译成SQL,所以会抛出翻译失败的异常。要保留数据库端查询,可通过以下两种方式改写:
方法1:使用值元组集合匹配
将内存中的objects转换为包含uId和cId的值元组列表,EF Core支持将值元组的Contains操作直接翻译成SQL的多列IN子句。
完整代码示例:
var objects = myObject; // IEnumerable<T> // 转换为值元组集合,避免重复枚举内存数据 var filterTuples = objects.Select(obj => (obj.uId, obj.cId)).ToList(); return await dbset .Where(entity => filterTuples.Contains((entity.uId, entity.cId))) .ToArrayAsync(cancellationToken) .ConfigureAwait(false);
方法2:使用匿名类型集合匹配
如果你的EF Core版本不支持值元组(较旧版本),可以改用匿名类型,EF Core能识别匿名类型的属性匹配逻辑。
完整代码示例:
var objects = myObject; // IEnumerable<T> var filterItems = objects.Select(obj => new { obj.uId, obj.cId }).ToList(); return await dbset .Where(entity => filterItems.Any(f => f.uId == entity.uId && f.cId == entity.cId)) .ToArrayAsync(cancellationToken) .ConfigureAwait(false);
原写法失败原因
- 第一种写法中,
objects.Any(...)是对内存IEnumerable的操作,EF Core无法将内存集合的遍历逻辑翻译成SQL语句。 - 第二种写法中,在查询表达式内创建自定义
Object实例并判断Contains,EF Core无法识别自定义对象的相等规则,无法生成对应的SQL比较逻辑。
内容的提问来源于stack exchange,提问作者G.Don
相关产品推荐
相关产品推荐

