升级到EF Core 3后,在以下代码处出现以下错误:
System.InvalidOperationException: '无法翻译LINQ表达式'DbSet.Max(c => Convert.ToInt32(c.ClaimNumber.Substring(c.ClaimNumber.Length - 6)))'。要么以可翻译的形式重写查询,要么通过插入对AsEnumerable()、AsAsyncEnumerable()、ToList()或ToListAsync()之一的调用来显式地切换到客户端评估。请参见https://go.microsoft.com/fwlink/?linkid=2101038了解更多信息。'
我还尝试过使用int.Parse而不是Convert.ToInt32,但仍然出现相同的错误。我理解这个错误信息。然而,在T-SQL中,使用CAST或CONVERT让SQL Server将字符串解析为int非常简单,我希望有一种简单的方法编写查询,以便它转换为服务器端操作,对吗? 更新 在Claudio的出色回答之后,我认为应该添加一些信息供下一个人参考。我认为解析是上述代码的问题所在,原因是以下代码可以正常运行并产生正确的结果:
然而,我深入挖掘后发现这是EF从代码中执行的SQL查询:
System.InvalidOperationException: '无法翻译LINQ表达式'DbSet.Max(c => Convert.ToInt32(c.ClaimNumber.Substring(c.ClaimNumber.Length - 6)))'。要么以可翻译的形式重写查询,要么通过插入对AsEnumerable()、AsAsyncEnumerable()、ToList()或ToListAsync()之一的调用来显式地切换到客户端评估。请参见https://go.microsoft.com/fwlink/?linkid=2101038了解更多信息。'
var maxId = Db.Claims
.Select(c => c.ClaimNumber.Substring(c.ClaimNumber.Length - 6))
.Max(x => Convert.ToInt32(x));
我还尝试过使用int.Parse而不是Convert.ToInt32,但仍然出现相同的错误。我理解这个错误信息。然而,在T-SQL中,使用CAST或CONVERT让SQL Server将字符串解析为int非常简单,我希望有一种简单的方法编写查询,以便它转换为服务器端操作,对吗? 更新 在Claudio的出色回答之后,我认为应该添加一些信息供下一个人参考。我认为解析是上述代码的问题所在,原因是以下代码可以正常运行并产生正确的结果:
var maxId = Db.Claims
.Select(c => c.ClaimNumber.Substring(c.ClaimNumber.Length - 6))
.AsEnumerable()
.Max(x => int.Parse(x));
然而,我深入挖掘后发现这是EF从代码中执行的SQL查询:
SELECT [c].[ClaimNumber], CAST(LEN([c].[ClaimNumber]) AS int) - 6
FROM [Claims] AS [c]
WHERE [c].[ClaimNumber] IS NOT NULL
显然,它没有做我想要的任何事情,因此,Claudio正确地指出了调用 Substring
是问题所在。
EF.Functions
。我不排除有一些 NuGet 包可以扩展 EF Core 并允许使用其他函数,但我不知道有哪些。 - Claudio Valerio