【问题标题】:How do I make contains case-insensitive in ef core 2?如何在 ef core 2 中设置不区分大小写?
【发布时间】:2018-06-21 08:31:34
【问题描述】:

我正在尝试通过搜索字符串过滤列表。上面写着in the doc on the blue note

  • IQueryable 为您提供Contains 的数据库提供程序实现。
  • IEnumerable 为您提供Contains 的 .NET Framework 实现
  • SQL Server 实例的默认设置不区分大小写。
  • 应避免使用ToUpper 进行显式不区分大小写的调用,因为它会降低性能。

我的过滤如下:

IQueryable<ApplicationUser> customers = 
    from u in _context.Users
    where (u.Customer != null && u.IsActive)
    select u;

if (!string.IsNullOrEmpty(searchString))
{
    customers = customers.Where(s => s.Email.Contains(searchString));
}

然而,这个解决方案是区分大小写的,我真的不明白为什么:因为我使用的是IQueryable,它应该使用数据库提供程序实现,默认情况下不区分大小写,对吧?

我正在使用 EF Core 2,目前只运行本地 MSSQLLocalDB。

【问题讨论】:

  • 您可以使用 String.ToLower() 对它们进行均衡化,然后比较这些临时字符串。您可能还想在其上运行 String.Normalize(),只是为了避免 Unicode 不一致。请注意,在循环中创建这么多字符串可能会产生大量的处理、内存和 GC 负载。字符串是最奇怪的类 请参阅这篇关于一般比较相等性的文章:codeproject.com/Articles/18714/…
  • 是的,调用 ToLower() 或 Normalize() 将具有与 ToUpper() 完全相同的性能开销,就像我在第 4 个要点中提到的那样。我希望避免这种情况,最好的解决方案可能就是更改我的数据库中的排序规则设置
  • @JasonReddekopp 关于 .Net 中 string 处理的问题与 LINQ to SQL 查询关系不大。
  • String.Contains 区分大小写,因此该部分是预期的。如果您跳过该部分,数据库不会将上下文中的所有用户还给您吗?

标签: c# sql entity-framework entity-framework-core contains


【解决方案1】:

您最好使用LIKE 运算符,例如

if (!String.IsNullOrEmpty(searchString))
{
    customers = customers.Where(x => EF.Functions.Like(x.Email, $"%{searchString}%"));
}

【讨论】:

  • 因为现在阅读您的代码的人都有明确的意图? .Contains() 无论如何都会(你希望)转换为 LIKE,但对于刚刚阅读代码的人来说可能并不明显。回复:区分大小写->这肯定在您的数据库的排序规则设置中?
  • @zaitsman 目的不是使用LIKE 进行模式匹配。目的是检查Email 是否包含指定的值,并且s.Email.Contains(searchString) 最好地记录该意图。您应该关心的是它是否成功转换为 SQL。最好的方法可能是也可能不是使用LIKE
  • @zaitsman 阅读代码的人很可能是 C# 程序员,他确切地知道 Contains 做了什么,并且可能不熟悉 SQL 和奇怪的通配符。
  • 包含在 ef core 中不会转换为 like 语句,它会转换为 CHARINDEX() 表达式
【解决方案2】:

从 EF Core 2.1 版开始,您可以使用 HasConversion()。但是数据库中的信息会以小写形式存储:

builder.Property(it => it.Email).HasConversion(v => v.ToLowerInvariant(), v => v);

我解决了一个类似的问题。这个改动解决了我所有的问题。

【讨论】:

    【解决方案3】:

    StringComparison 是我的答案。

    customers = customers.Where(s => s.Email.Contains(searchString, StringComparison.CurrentCultureIgnoreCase));

    customers = customers.Where(s => s.Email.Contains(searchString, StringComparison.InvariantCultureIgnoreCase));

    为我工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-05-11
      • 2020-03-24
      • 1970-01-01
      • 2020-07-22
      • 2021-11-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多