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

时间:2017-04-07 12:13:59

标签: c# database postgresql linq entity-framework-core

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

以下仅在使用正确的关键字框时输出结果。

context.Counties.Where(x => x.Name.Contains(keyword)).ToList();

我做错了什么?

6 个答案:

答案 0 :(得分:11)

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

如果要以不区分大小写的方式比较字符串,则可以使用DbFunctions来完成工作。

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

更新到@Gert:

问题中的部分假设不正确。 string.Contains不会转换为LIKE expression,即使在ef核心版本<= 1.0(我认为)中使用过这种情况也是如此。

  • SQLServerstring.contains转换为CHARINDEX(),在oracle中和sqlite转换为instr(),默认情况下区分大小写,除非数据库或列排序规则否则定义(同样,对于postgresql我也不知道)。
  • 在所有情况下,EF.Functions.Like()都会转换为SQL LIKE表达式,默认情况下,该表达式不区分大小写,除非另行定义了db或column排序规则。

是的,这全都归结为排序规则,但是-如果我错了,请纠正我-根据您使用的上述方法中的哪一种,代码可以对区分大小写/不区分大小写的搜索产生影响。 / p>

现在,我可能尚未完全了解最新信息,但我认为EF核心迁移不会自然地处理数据库排序规则,除非您已经手动创建了表,否则最终将使用默认排序规则(区分大小写) sqlite,老实说,我对其他人一无所知。

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

  1. 使用此trick,使用DbContext.OnModelCreating()指定创建时的列排序规则。
  2. string.Contains替换为EF.Functions.Like()
  3. 或者等待discussion中仍然有希望的功能:EF.Functions.Collate()函数

答案 1 :(得分:3)

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

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

阅读此答案:Returning IEnumerable vs. IQueryable

答案 2 :(得分:1)

只需尝试:

您可以Lower case字段和搜索值

  context.Counties.Where(x => x.Name.ToLower().Contains(keyword.ToLower())).ToList();

或者您可以Upper Case提交并搜索值

context.Counties.Where(x => x.Name.ToUpper().Contains(keyword.ToUpper())).ToList();

答案 3 :(得分:0)

我的答案将与NpgSQL有关。

    PostgreSQL中的
  1. EF.Functions.Like()区分大小写,但是您可以使用位于EF.Functions.ILike() method中的Npgsql.EntityFrameworkCore.PostgreSQL扩展名assembly

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

示例:

context.Counties.Where(x => x.Name.ToLower().Contains(keyword.ToLower())).ToList();

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

答案 4 :(得分:0)

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

例如

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

有关更多详细信息,请参见msdn链接

https://docs.microsoft.com/en-us/ef/core/miscellaneous/collations-and-case-sensitivity

答案 5 :(得分:0)

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

items = items.Where(i => 
    i.Name.Contains(value, StringComparison.InvariantCultureIgnoreCase));

默认行为似乎区分大小写,但是您可以使用StringComparison.InvariantCulture对其进行显式设置。

有关其他信息,请在我的博客上查看this post

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