关于.net:LINQ-to-SQL中不区分大小写的字符串比较

Case insensitive string compare in LINQ-to-SQL

我已经读到,使用toupper和tolower执行不区分大小写的字符串比较是不明智的,但是在linq to sql方面,我看不到其他选择。string.compare的ignorecase和compareOptions参数被linq to sql忽略(如果使用区分大小写的数据库,则即使要求进行不区分大小写的比较,也会得到区分大小写的比较)。托洛威尔或托普是这里最好的选择吗?一个比另一个好吗?我本以为我在某个地方读到了"笨蛋"更好,但我不知道这是否适用于这里。(我做了很多代码审查,每个人都在使用Tolower。)

1
Dim s = FROM ROW IN context.Table WHERE String.Compare(ROW.Name,"test", StringComparison.InvariantCultureIgnoreCase) = 0

这转换为一个SQL查询,它只将row.name与"test"进行比较,不会在区分大小写的数据库上返回"test"和"test"。


正如你所说,toupper和tolower之间有一些重要的区别,当你试图进行不区分大小写的平等检查时,只有一个是可靠准确的。

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

1
String.Equals(ROW.Name,"test", StringComparison.OrdinalIgnoreCase)

但是请注意,在这种情况下这不起作用!因此,我们只能使用ToUpperToLower

注意顺序案例以确保安全。但是,您使用的区分大小写检查的具体类型取决于您的目的。但是,通常在排序时使用equals进行相等性检查和比较,然后为作业选择正确的StringComparison。

迈克尔·卡普兰(一位公认的文化和性格处理权威,如此)在《图珀与托洛威尔》中有相关的职位:

  • http://www.siao2.com/2007/10/01/5218976.aspx
  • http://www.siao2.com/2005/03/10/391564.aspx

他说:"string.toupper–使用toupper而不是tolower,并指定不变的区域性以获取操作系统的大小写规则。"


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

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


我用lambda表达式尝试了这个方法,它起作用了。

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


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

1
String.Equals(ROW.Name,"test", StringComparison.OrdinalIgnoreCase)

解决这个问题的方法是删除空格,然后转换它的大小写,然后像这样选择

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

注意在这种情况下

customname是与数据库值匹配的值

userstbs是类

标题是数据库列


1
WHERE ROW.name.StartsWith(q, TRUE, System.Globalization.CultureInfo.CurrentCulture)


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

1
2
3
4
5
6
7
8
RESULT = entRepos.FindAllEntities()
    .Where(e => e.EntitySearchText.Contains(item));

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


要执行区分大小写的LINQ to SQL查询,请使用以下方法之一指定服务器数据类型,将"字符串"字段声明为区分大小写;

1
VARCHAR(4000) COLLATE SQL_Latin1_General_CP1_CS_AS

1
nvarchar(MAX) COLLATE SQL_Latin1_General_CP1_CS_AS

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

当使用Visual Studio DBML设计器查看属性时,可以在"服务器数据类型"字段中输入此值。

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


如果将不区分大小写的字符串传递给Linq to SQL,它将以不变的方式传递给SQL,并在数据库中进行比较。如果要在数据库中进行不区分大小写的字符串比较,只需创建一个进行比较的lambda表达式,Linq to SQL提供程序会将该表达式转换为字符串完整的SQL查询。

例如,此Linq查询:

1
2
3
FROM USER IN Users
WHERE USER.Email =="[email protected]"
SELECT USER

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

1
2
3
4
5
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"[email protected]"

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


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

使用string.equals将很可能(我猜)从SQL Server返回所有行,然后在.NET中进行比较,因为它是一个不能转换为T-SQL的.NET表达式。

换句话说,使用表达式将增加您的数据访问量,并删除您使用索引的能力。它适用于小桌子,你不会注意到不同之处。在一张大桌子上,它的性能可能很差。

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

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