实体框架 LINQ 中的 contains 方法不区分大小写。

11

我在Entity Framework上遇到了一些令人抓狂的问题,但我就是找不到解决方案。

我想要做的是,为正在运行的搜索功能比较字符串。它基本上是这样的: collection.Where(c => c.Name.Contains(searchTerm));其中searchTerm是由用户传递的字符串。

无论我去哪里寻找答案,都是以下两种方法:

  1. 都使用toUpper()函数将两个字符串进行更改,或者

  2. 将排序规则设置为大小写不敏感的排序规则。

然而这两种方法都不能解决我的问题。以下是一个没有答案的类似问题:Entity Framework - case insensitive Contains?

如果采用第一种方法将导致获取数据库中的每一行,然后执行toUpper()函数来查看是否匹配。从性能的角度来看,这是不能接受的。

第二种方法似乎更有可能是有效的解决方案,但由于某种原因却无法工作。我有两个数据库。一个是本地的,一个是远程的。远程MSSQL数据库的排序规则是“Finnish_Swedish_CI_AS”,这意味着它不区分大小写?本地数据库是自动生成的本地DB,属性“大小写敏感”设置为False。

无论我使用这两个数据库中的哪一个,用户仍然始终是大小写敏感的。

请问有人可以解释一下这是为什么吗,这样我就可以继续我的悲惨生活了吗?

谢谢, Robin Dorbell


那么你的意思是IndexOf解决方案不会告诉实体框架在比较之前检索每条记录? - Robin Dorbell
你读过关于不同编程语言的这个答案了吗?https://dev59.com/D3RB5IYBdhLWcg3w-8Lo 它暗示你应该使用CultureInfo类。 - Dave C
@JiggsJedi 我已经阅读了它,但是它并没有解决我的问题,因为我遇到的问题是当我的数据库不区分大小写时,Entity Framework 会以区分大小写的方式进行比较。 - Robin Dorbell
2
你确定搜索是在服务器上执行吗?检查“_collection”的类型?如果它是“IEnumerable<?>”,则查询将在C#代码中执行,而不是在数据库服务器上执行(并且区分大小写)。如果它是“IQueryable<?>”,那么它可能正在数据库服务器上执行。 - Grax32
1
@Grax 可能就是这样。集合类型是 ICollection<T> - Robin Dorbell
显示剩余2条评论
3个回答

14

对我来说,它从未区分大小写,但我想这只是我设置数据库的方式。您绝对可以使用将它们都转换为大写的第一选项,EF不会将它们拉入内存进行操作,只需通知SQL服务器即可。例如:

string searchTerm = "Some Text";

dbcontext.Table.Where (t => t.Column.ToLower().Contains(searchTerm.ToLower()));

生成以下SQL语句(大概是这样的,我用的是LinqToSql,但EF应该很相似):

-- Region Parameters
DECLARE @p0 NVarChar(1000) = '%some text%'
-- EndRegion
SELECT *
FROM [Table] AS [t0]
WHERE LOWER([t0].[Column]) LIKE @p0

好的!感谢您提供详细的答案。很有趣的知识。然而,这似乎并不是我的问题所在。问题在于我在集合上使用了ICollection<T>,导致服务器上进行了区分大小写的比较。 - Robin Dorbell
哦,那么你的集合是从哪里来的呢?如果它已经在内存中了,那么调用.ToUpper()对它们也不会有太大的影响。 - Ben

11

从评论中可以看出,问题的提出者首先将IQueryable列表转换为了ICollection,这意味着任何后续的LINQ都是在本地运行而不是有机会被转换为SQL。

例如,

    // Should be IQueryable<T>
    ICollection<User> users = context.Users;

    // This is executed in code rather than SQL, and so is case SENSITIVE
    users = users.Where(c => c.Name.Contains(searchTerm));

这可能有助于调试问题:如何查看由实体框架生成的SQL?


-1
使用 string.Equals。
collection.Where(c => string.Equals(c.Name, searchTerm, StringComparison.CurrentCultureIgnoreCase));

此外,您无需担心空值,并且只返回您想要的信息。

对于区分大小写,请使用StringComparision.CurrentCulture。

collection.Where(c => string.Equals(c.Name, searchTerm, StringComparison.CurrentCulture));

“Equals” 会尝试精确匹配单词 - 这不是我想要的。问题就像 Dunc 所写的那样,查询是在从服务器获取所有内容之后执行的。 - Robin Dorbell
Entity Framework 5.0及更高版本在使用StringComparison重载的string.Equals时会抛出异常。 https://learn.microsoft.com/en-us/ef/core/miscellaneous/collations-and-case-sensitivity - Gregor A. Lamche

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