LINQ-to-SQL中不区分大小写的字符串比较

时间:2009-05-08 18:41:00

标签: .net sql vb.net linq linq-to-sql

我已经读过使用ToUpper和ToLower来执行不区分大小写的字符串比较是不明智的,但是在LINQ-to-SQL方面我没有别的选择。 LINQ-to-SQL忽略String.Compare的ignoreCase和CompareOptions参数(如果您使用区分大小写的数据库,即使您要求不区分大小写的比较,也会得到区分大小写的比较)。 ToLower或ToUpper是最好的选择吗?这个比那个好吗?我以为我读过ToUpper更好的地方,但我不知道这是否适用于此。 (我正在进行大量的代码审查,每个人都在使用ToLower。)

Dim s = From row In context.Table Where String.Compare(row.Name, "test", StringComparison.InvariantCultureIgnoreCase) = 0

这转换为一个SQL查询,它简单地将row.Name与“test”进行比较,并且不会在区分大小写的数据库上返回“Test”和“TEST”。

10 个答案:

答案 0 :(得分:109)

正如您所说,ToUpper和ToLower之间存在一些重要的差异,当您尝试进行不区分大小写的相等性检查时,只有一个是可靠的。

理想情况下,进行不区分大小写的相等检查的最佳方法是

String.Equals(row.Name, "test", StringComparison.OrdinalIgnoreCase)

请注意,但在这种情况下无法正常工作!因此,我们会遇到ToUpperToLower

请注意 Ordinal IgnoreCase,以确保安全。但确切地说,您使用的案例(中)敏感检查的类型取决于您的目的。但是通常在排序时使用Equals进行等式检查和比较,然后为该作业选择正确的StringComparison。

Michael Kaplan(文化和角色处理方面的公认权威)在ToUpper与ToLower上有相关的帖子:

他说“String.ToUpper - 使用ToUpper而不是ToLower,并指定InvariantCulture以获取操作系统规则

答案 1 :(得分:71)

我用过 System.Data.Linq.SqlClient.SqlMethods.Like(row.Name, "test") 在我的查询中。

这会执行不区分大小写的比较。

答案 2 :(得分:7)

我使用Lambda表达式尝试了这个,它起作用了。

List<MyList>.Any (x => (String.Equals(x.Name, name, StringComparison.OrdinalIgnoreCase)) && (x.Type == qbType) );

答案 3 :(得分:0)

如果将不区分大小写的字符串传递给LINQ-to-SQL,它将不会更改地传递给SQL,并且将在数据库中进行比较。如果要在数据库中进行不区分大小写的字符串比较,您只需创建一个执行比较的lambda表达式,LINQ-to-SQL提供程序将该表达式转换为字符串完整的SQL查询。 / p>

例如这个LINQ查询:

from user in Users
where user.Email == "foo@bar.com"
select user

由LINQ-to-SQL提供程序转换为以下SQL:

SELECT [t0].[Email]
FROM [User] AS [t0]
WHERE [t0].[Email] = @p0
-- note that "@p0" is defined as nvarchar(11)
-- and is passed my value of "foo@bar.com"

正如您所看到的,字符串参数将在SQL中进行比较,这意味着事情应该按照您期望的方式工作。

答案 4 :(得分:0)

要执行区分大小写的Linq to Sql查询,请通过使用以下方法之一指定服务器数据类型来声明“字符串”字段区分大小写;

varchar(4000) COLLATE SQL_Latin1_General_CP1_CS_AS 

nvarchar(Max) COLLATE SQL_Latin1_General_CP1_CS_AS

注意:上述排序规则类型中的“CS”表示“区分大小写”。

使用Visual Studio DBML Designer查看属性时,可以在“服务器数据类型”字段中输入此内容。

有关详细信息,请参阅http://yourdotnetdesignteam.blogspot.com/2010/06/case-sensitive-linq-to-sql-queries.html

答案 5 :(得分:0)

以下两阶段方法适用于我(VS2010,ASP.NET MVC3,SQL Server 2008,Linq to SQL):

result = entRepos.FindAllEntities()
    .Where(e => e.EntitySearchText.Contains(item));

if (caseSensitive)
{
    result = result
        .Where(e => e.EntitySearchText.IndexOf(item, System.StringComparison.CurrentCulture) >= 0);
}

答案 6 :(得分:0)

where row.name.StartsWith(q, true, System.Globalization.CultureInfo.CurrentCulture)

答案 7 :(得分:0)

有时,存储在数据库中的值可能包含空格,因此运行此操作可能会失败

String.Equals(row.Name, "test", StringComparison.OrdinalIgnoreCase)

解决这个问题的方法是删除空格然后转换它的情况然后像这样选择

 return db.UsersTBs.Where(x => x.title.ToString().ToLower().Replace(" ",string.Empty).Equals(customname.ToLower())).FirstOrDefault();

请注意

customname 是与数据库值匹配的值

UsersTBs 是班级

标题是数据库列

答案 8 :(得分:0)

使用 .NET core,System.Data.Linq.SqlClient.SqlMethods 不可用,改用这个

EF.Functions.Like(row.Name, "test")

答案 9 :(得分:-1)

请记住,查询是否有效以及是否有效之间存在差异!当语句的目标是SQL Server时,LINQ语句将转换为T-SQL,因此您需要考虑将要生成的T-SQL。

使用String.Equals很可能(我猜)从SQL Server中恢复所有行,然后在.NET中进行比较,因为它是一个无法转换为T-SQL的.NET表达式。 / p>

换句话说,使用表达式将增加您的数据访问权并删除您使用索引的能力。它适用于小桌子,你不会注意到它们的区别。在一张大桌子上,它的表现非常糟糕。

这是LINQ存在的问题之一;人们不再考虑他们所写的陈述将如何实现。

在这种情况下,没有办法在不使用表达式的情况下做你想做的事 - 即使在T-SQL中也是如此。因此,您可能无法更有效地执行此操作。即使上面给出的T-SQL答案(使用带有排序规则的变量)也很可能导致索引被忽略,但如果它是一个大表,则值得运行该语句并查看执行计划以查看是否使用了索引