EF Core 3.0 正确翻译 string.Equals 的 ordinalIgnoreCase 参数

16

在 EF Core 3.0 之前,这个运行良好(在服务器和客户端上都可用):

var exists = await _context.Countries.AsNoTracking().AnyAsync(x => x.CountryCode.Equals(country.CountryCode, StringComparison.OrdinalIgnoreCase));

在EF Core 3.0中,如何最好/首选翻译string.Equals(str, StringComparison.OrdinalIgnoreCase)部分,以便查询仅在服务器端评估。

var exists = await _context.Countries.AsNoTracking().AnyAsync(x => x.CountryCode.ToUpper() == country.CountryCode.ToUpper());
或者
var exists = await _context.Countries.AsNoTracking().AnyAsync(x => x.CountryCode.ToLower() == country.CountryCode.ToLower());
或者
var exists = await _context.Countries.AsNoTracking().AnyAsync(x => x.CountryCode.ToUpperInvariant() == country.CountryCode.ToUpperInvariant());
或者
var exists = await _context.Countries.AsNoTracking().AnyAsync(x => x.CountryCode.ToLowerInvariant() == country.CountryCode.ToLowerInvariant());

还是其他什么?


这是代码中的一个错误,而不是EF的问题。大小写敏感性由的排序规则控制。如果该列使用大小写不敏感的排序规则,则可以进行大小写不敏感的匹配。索引也使用排序规则,因此尝试使用不同的规则进行匹配或更糟糕的是应用任何类型的函数,都会阻止服务器使用任何索引。 - Panagiotis Kanavos
真正的解决方案是由L.Trabacchin发布的。完全删除Equals并确保该列使用不区分大小写的排序规则。问题中发布的所有片段都会导致糟糕的查询。x => x.CountryCode.==country.CountryCode将完美地工作。 - Panagiotis Kanavos
1
顺便提一下,这意味着你的代码已经存在严重的性能缺陷,因为EF Core禁用了客户端评估。直到现在,你的查询会在过滤之前将所有内容加载到客户端内存中。 - Panagiotis Kanavos
1个回答

23

您不应该这样做,也不应该使用已接受的答案方法,应该只使用String.Equals()方法而无需参数,并在创建或迁移期间配置数据库排序规则。


看起来今天我学到了新东西。谢谢。我理解的是默认情况下已经不区分大小写(Latin1_General_CI_AS)了,对吗? - juFo
1
通常情况下是这样,但如果对你来说非常重要,那么请确保它是这样的。看一下:有很多方法可以做到这一点:https://dev59.com/G2ct5IYBdhLWcg3wgNcy - L.Trabacchin
3
我们如何支持这种情况:在一个查询中,我需要区分大小写,在另一个查询中则不需要。例如,我们的搜索应该是不区分大小写的,但当我使用实体进行精确匹配时,我希望按照大小写来加载。 - Petr J
ef core 支持自定义查询...配置默认情况,然后使用自定义的查询。 https://learn.microsoft.com/en-us/ef/core/querying/raw-sql - L.Trabacchin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接