【问题标题】:Filtering by an untranslatable method using EF Core 3.1使用 EF Core 3.1 通过不可翻译的方法进行过滤
【发布时间】:2020-10-19 07:11:24
【问题描述】:

在带有 SQL Server 数据库的 Web 应用程序中,我使用“存储库模式”实现了数据访问层。为了根据电子邮件过滤User,我使用了这样的表达式:

var emailFilter = "user@example.com";
var query = _dbContext.Set<User>().Where(x => x.Email.Normalize() == emailFilter.Normalize());
var result = query.ToListAsync(); 

但是 EF Core 抛出了一个异常,上面写着:

...无法翻译。以可翻译的形式重写查询,或通过插入对 AsEnumerable()、AsAsyncEnumerable()、ToList() 或 ToListAsync() 的调用显式切换到客户端评估

我的用户表中有超过 20 万个用户,我不想在客户端过滤数据。

上述代码只是一个示例,我指的是其他使用更复杂方法的用例。

现在,如何使用复杂的函数在服务器端过滤数据?

【问题讨论】:

  • 仅当您可以将它们重写为表达式时。但是为什么存储的电子邮件地址应该在过滤之前被“规范化”呢?他们不应该在保存之前进行标准化吗?
  • @GertArnold 这只是一个示例,我的意思是如何处理不可翻译的函数?我应该使用 T-SQL 实现这些方法吗?
  • 要么(并将其映射到上下文中的DbFunction)要么将其重写为表达式。但总的来说,您应该始终避免在过滤之前使用函数。它不会执行。
  • 如果有一种“通用的”、机械的方式来转换不可翻译的方法以便它们可以工作,为什么 EF 团队不会在 EF 内部实现这种转换?
  • 通用“使用不可翻译方法的服务器端过滤”没有意义。你要么让它可翻译,要么它不会在服务器端运行。

标签: c# sql-server .net-core ef-core-3.1


【解决方案1】:

我建议你,首先通过批量更新来规范你在数据​​库中的电子邮件:

Z.EntityFramework.Plus.EFCore

_dbContext.Set<User>().update(x => new User {Email =  x.Email.Normalize()}  ;

然后

emailFilter = ("user@example.com").Normalize();
var query = _dbContext.Set<User>().Where(x => x.Email  == emailFilter);
var result = query.ToListAsync(); 

这是一个实例解决方案

【讨论】:

  • 感谢您的回复。但我的意思是任何其他不可翻译的方法的通用解决方案。我已经更新了问题
  • Ef convert c# to sql 一些复杂的函数不能翻译。你必须简化你的代码。
【解决方案2】:

对于非标准的使用纯 sql 查询...

var emailFilter = "user@example.com";
var result = await _dbContext.Users.FromSqlRaw($"SELECT * FROM dbo.Users WHERE LOWER(Email) = {emailFilter}").ToListAsync(); 

或者使用函数

var emailFilter = "user@example.com";
var result = await _dbContext.Users.Where(x => EF.Functions.Like(x.Email, $"%{emailFilter}%")).ToListAsync(); 

以性能为代价...

【讨论】:

    猜你喜欢
    • 2021-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-02
    • 2018-09-25
    • 1970-01-01
    • 2020-09-10
    相关资源
    最近更新 更多