Entity Framework 5.0 Contains/Equals/StartsWith/EndWith in Any 无法像在 EF Core 2.2 中那样在 SQL 中翻译
Entity Framework 5.0 Contains/Equals/StartsWith/EndWith in Any cannot be translated in SQL as it was in EF Core 2.2
我正在尝试将 Linq 查询从 EF Core 2.2 迁移到 EF Core 5.0,它在 2.2 中运行完美
var foo = await _baseRepository.GetQueryable<User>().Where(i => new[] { "os", "man" }.Any(j => i.Email.Contains(j))).ToListAsync();
错误
The LINQ expression 'DbSet<User>()
.Where(u => string[] { "os", "man", }
.Any(j => u.Email.Contains(j)))' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
我也试过了new[] { "os", "man" }.ToList()/AsEnumerable()
这也有效
var foo = await _baseRepository.GetQueryable<User>().Where(i => new[] { "os" }.Any(j => i.Email.Equals(j))).ToListAsync();
结果查询
SELECT * FROM User WHERE Email = "os"
但是这个 不等于 (... !Equals(..)) 不起作用
var foo = await _baseRepository.GetQueryable<User>().Where(i => new[] { "os" }.Any(j => !i.Email.Equals(j))).ToListAsync();
我也试过StartsWith/EndsWith但是我得到了错误
相关问题:
不久前(2 年);但是很多 LINQ 语句从 2.2 升级到 3.0。您的 link 列出了原因(如果 Core 3 无法将 LINQ 转换为 SQL 语句并需要在没有显式 ToEnumerable()
的情况下将记录拉入内存,则会引发异常)和建议的解决方案。
所以,不清楚你在问什么。不幸的是,这些错误只会在运行时出现;所以你需要遍历所有这些并且 - 最好 - 使用映射到 SQL 的 LINQ 选项;或者 - 如果不可能 - 显式调用 ToEnumerable()
如果您需要在 升级之前 修复它们,您可以致电 DbContext
:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) => optionsBuilder
.ConfigureWarnings(warnings => warnings.Log(RelationalEventId.QueryClientEvaluationWarning));
如前所述,这在 EF Core 2.2 中有效,因为它们允许客户端评估,这有效地做了一个大的“SELECT *”或至少应用了他们可以进行的过滤,然后进行了不受支持的评估在记忆中。
在您的 EF Core 2.2 示例中:
var foo = await _baseRepository.GetQueryable<User>()
.Where(i => new[] { "os", "man" }
.Any(j => i.Email.Contains(j)))
.ToListAsync();
在 EF Core 5 中会是这样的:
var foo = await _baseRepository.GetQueryable<User>()
.ToListAsync() // <- materialize for client-side evaluation.
.Where(i => new[] { "os", "man" }
.Any(j => i.Email.Contains(j)))
.ToListAsync();
**免责声明:我不能 100% 确定它是否有效。您可能需要在 Get all 上等待 ToListAsync()
,然后将过滤作为单独的操作进行。
var users = await _baseRepository.GetQueryable<User>()
.ToListAsync(); // <- materialize for client-side evaluation.
var foo = await users.Where(i => new[] { "os", "man" }
.Any(j => i.Email.Contains(j)))
.ToListAsync();
虽然 EF 可以理解 string.Contains()
,但它无法使用 .Any()
对内存中的集合进行解析。虽然这肯定不理想,因为您在过滤之前加载 所有 用户。
要修复它以便 EF 可以翻译,它将是这样的:
var foo = await _baseRepository.GetQueryable<User>()
.Where(i=> i.Email.Contains("os")
|| i.Email.Contains("man")
.ToListAsync();
但是,如果您想变得更加动态,例如让内存列表由 variable/configurable 集组成,那么您需要查看 Dynamic Linq。 (https://dynamic-linq.net/) 具体来说,它是 Nuget 包,可帮助您构建 EF 可以执行的表达式。这将允许您从一组值动态组成 OR 表达式,作为 Where
子句的一部分执行。
我正在尝试将 Linq 查询从 EF Core 2.2 迁移到 EF Core 5.0,它在 2.2 中运行完美
var foo = await _baseRepository.GetQueryable<User>().Where(i => new[] { "os", "man" }.Any(j => i.Email.Contains(j))).ToListAsync();
错误
The LINQ expression 'DbSet<User>()
.Where(u => string[] { "os", "man", }
.Any(j => u.Email.Contains(j)))' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
我也试过了new[] { "os", "man" }.ToList()/AsEnumerable()
这也有效
var foo = await _baseRepository.GetQueryable<User>().Where(i => new[] { "os" }.Any(j => i.Email.Equals(j))).ToListAsync();
结果查询
SELECT * FROM User WHERE Email = "os"
但是这个 不等于 (... !Equals(..)) 不起作用
var foo = await _baseRepository.GetQueryable<User>().Where(i => new[] { "os" }.Any(j => !i.Email.Equals(j))).ToListAsync();
我也试过StartsWith/EndsWith但是我得到了错误
相关问题:
不久前(2 年);但是很多 LINQ 语句从 2.2 升级到 3.0。您的 link 列出了原因(如果 Core 3 无法将 LINQ 转换为 SQL 语句并需要在没有显式 ToEnumerable()
的情况下将记录拉入内存,则会引发异常)和建议的解决方案。
所以,不清楚你在问什么。不幸的是,这些错误只会在运行时出现;所以你需要遍历所有这些并且 - 最好 - 使用映射到 SQL 的 LINQ 选项;或者 - 如果不可能 - 显式调用 ToEnumerable()
如果您需要在 升级之前 修复它们,您可以致电 DbContext
:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) => optionsBuilder
.ConfigureWarnings(warnings => warnings.Log(RelationalEventId.QueryClientEvaluationWarning));
如前所述,这在 EF Core 2.2 中有效,因为它们允许客户端评估,这有效地做了一个大的“SELECT *”或至少应用了他们可以进行的过滤,然后进行了不受支持的评估在记忆中。
在您的 EF Core 2.2 示例中:
var foo = await _baseRepository.GetQueryable<User>()
.Where(i => new[] { "os", "man" }
.Any(j => i.Email.Contains(j)))
.ToListAsync();
在 EF Core 5 中会是这样的:
var foo = await _baseRepository.GetQueryable<User>()
.ToListAsync() // <- materialize for client-side evaluation.
.Where(i => new[] { "os", "man" }
.Any(j => i.Email.Contains(j)))
.ToListAsync();
**免责声明:我不能 100% 确定它是否有效。您可能需要在 Get all 上等待 ToListAsync()
,然后将过滤作为单独的操作进行。
var users = await _baseRepository.GetQueryable<User>()
.ToListAsync(); // <- materialize for client-side evaluation.
var foo = await users.Where(i => new[] { "os", "man" }
.Any(j => i.Email.Contains(j)))
.ToListAsync();
虽然 EF 可以理解 string.Contains()
,但它无法使用 .Any()
对内存中的集合进行解析。虽然这肯定不理想,因为您在过滤之前加载 所有 用户。
要修复它以便 EF 可以翻译,它将是这样的:
var foo = await _baseRepository.GetQueryable<User>()
.Where(i=> i.Email.Contains("os")
|| i.Email.Contains("man")
.ToListAsync();
但是,如果您想变得更加动态,例如让内存列表由 variable/configurable 集组成,那么您需要查看 Dynamic Linq。 (https://dynamic-linq.net/) 具体来说,它是 Nuget 包,可帮助您构建 EF 可以执行的表达式。这将允许您从一组值动态组成 OR 表达式,作为 Where
子句的一部分执行。