实体框架核心 - 包含区分大小写还是不区分大小写?

001*_*001 12 c# linq database postgresql entity-framework-core

Entity Framework核心中的"Contains"应该等同于%%运算符的SQL%.因此"Contains"应该不区分大小写,但它区分大小写!(至少在postgres ????)

以下仅在使用正确的关键字大小写时输出结果.

context.Counties.Where(x => x.Name.Contains(keyword)).ToList();
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?

Dar*_*rse 21

过去曾经是旧版EF核心的情况.现在string.Contains是区分大小写的,例如对于sqlite,它映射到sqlite函数`instr()'(我不知道对于postgresql).

如果要以不区分大小写的方式比较字符串,则可以使用DbFunction来执行作业.

context.Counties.Where(x => EF.Functions.Like(x.Name, $"%{keyword}%")).ToList();
Run Code Online (Sandbox Code Playgroud)

更新@Gert:

问题中的部分假设是不正确的.string.Contains不转换成LIKE expression即使它曾经是EF核版本的情况下<= 1.0(我认为).

  • SQLServer的 string.contains转换为CHARINDEX(),在预言源码instr()其是除非分贝或列排序规则定义,否则(同样,我不知道对PostgreSQL)情况下,通过默认敏感.
  • 在所有情况下,EF.Functions.Like()转换为SQL LIKE表达式,默认情况下不区分大小写,除非另外定义了db或列排序规则.

所以是的,这一切都归结为整理但是 - 如果我错了,请纠正我 - 在某种程度上,代码会对区分大小写/不敏感的搜索产生影响,具体取决于您使用上述哪种方法.

现在,我可能不完全是最新的,但我不认为EF核心迁移会自然地处理数据库归类,除非你已经手动创建了表,否则最终会得到默认的归类(对于sqlite和我来说区分大小写)老实说,不知道其他人).

回到原始问题,如果未来版本中没有3个,则至少有2个选项可以执行此不区分大小写的搜索:

  1. 使用DbContext.OnModelCreating()使用此技巧指定创建时的列排序规则
  2. 替换你string.ContainsEF.Functions.Like()
  3. 或者等待仍在讨论的有前途的功能:EF.Functions.Collate()功能

  • 不对。它仅取决于数据库排序规则。EF 在这里没有*任何*影响,更不用说 EF *版本*了。 (3认同)
  • `EF.Functions.ILike`... 发现这个真是太棒了。谢谢。 (2认同)
  • 安全怎么样?这似乎很可能不安全: EF.Functions.Like(x.Name, $"%{keyword}%") (2认同)

小智 12

在查询中使用显式排序规则

例如

var customers = context.Customers
.Where(c => EF.Functions.Collate(c.Name, "SQL_Latin1_General_CP1_CS_AS") == "John")
.ToList();
Run Code Online (Sandbox Code Playgroud)

更多详情请参见msdn链接

https://learn.microsoft.com/en-us/ef/core/miscellaneous/collat​​ions-and-case-sensitivity


top*_*ool 7

就试一试吧 :

您可以Lower case字段和搜索值

  context.Counties.Where(x => x.Name.ToLower().Contains(keyword.ToLower())).ToList();
Run Code Online (Sandbox Code Playgroud)

或者您可以Upper Case归档并搜索值

context.Counties.Where(x => x.Name.ToUpper().Contains(keyword.ToUpper())).ToList();
Run Code Online (Sandbox Code Playgroud)

  • 这可能会导致非常大的性能问题,尤其是对于 PostgreSQL,请参阅上面的 @Stas 答案,以避免您可能面临的性能灾难 (4认同)

Sta*_*cev 6

我的答案将与NpgSQL有关。

  1. EF.Functions.Like()在PostgreSQL是区分大小写的,但是你可以使用EF.Functions.ILike()扩展方法位于Npgsql.EntityFrameworkCore.PostgreSQL 装配

  2. 如果在构建查询的地方没有引用实体框架程序集,则可以使用组合ToLower()Contains()方法,因为Npgsql 能够转换ToLower()方法来更正SQL。

例:

context.Counties.Where(x => x.Name.ToLower().Contains(keyword.ToLower())).ToList();
Run Code Online (Sandbox Code Playgroud)

关于第二种方法,请记住:您可能会遇到性能问题,并且可能会遇到与编码相关的问题。

  • 性能地狱正是让我来到这里的原因,我使用的是第二种方法,我无法理解为什么我的查询需要 5 分钟才能执行,请非常小心第二种方法,性能的变化是可怕的。 (2认同)

Kfi*_*Guy 5

IQueryable.Where 在数据库中执行,因此很可能不区分大小写。

IEnumerable.Where使用 C# String.Contains,因此区分大小写。

阅读此答案:返回 IEnumerable 与 IQueryable

  • IQueriable 的行为取决于数据库。例如,在 SQL Server 中,它不区分大小写,但对于 postgres,它区分大小写 (9认同)

Dar*_*eal 5

使用 Entity Framework Core 3.1 和 MySQL / MariaDB 提供程序,您可以StringComparison.InvariantCultureIgnoreCase通过以下方式手动设置大小写(不)敏感度:

items = items.Where(i => 
    i.Name.Contains(value, StringComparison.InvariantCultureIgnoreCase));
Run Code Online (Sandbox Code Playgroud)

默认行为似乎区分大小写,但是您可以使用StringComparison.InvariantCulture.

有关更多信息,请查看这篇文章在我的博客。

我不知道它是否也适用于以前的版本(将相应地检查并更新此答案)。

  • 它的翻译如下:`WHERE (LOCATE(CONVERT(LCASE(@__value_0) USING utf8mb4) COLLATE utf8mb4_bin, LCASE(b.Name)) &gt; 0)` (2认同)