不区分大小写的string比较在LINQ到SQL中
我读过使用ToUpper和ToLower来执行不区分大小写的string比较是不明智的,但是当涉及到LINQ-to-SQL时,我看不到任何其他select。 String.Compare的ignoreCase和CompareOptions参数被LINQ-to-SQL忽略(如果您使用的是区分大小写的数据库,即使您要求区分大小写的比较,也可以区分大小写)。 ToLower或ToUpper在这里最好的select? 这个比那个好吗? 我以为我在某个地方看过ToUpper比较好,但我不知道这里是否适用。 (我正在做很多代码评论,每个人都在使用ToLower。)
Dim s = From row In context.Table Where String.Compare(row.Name, "test", StringComparison.InvariantCultureIgnoreCase) = 0
这转换为一个SQL查询,它简单地将row.Name与“test”进行比较,并且不会在区分大小写的数据库上返回“Test”和“TEST”。
正如你所说,ToUpper和ToLower之间有一些重要的区别,当你试图进行不区分大小写的等式检查时,只有一个是可靠的。
理想情况下,执行不区分大小写的平等检查的最佳方法是:
String.Equals(row.Name, "test", StringComparison.OrdinalIgnoreCase)
请注意有序的 IgnoreCase,以确保安全。 但是,确切地说,你使用的情况(中)敏感检查的types取决于你的目的是什么。 但是在一般情况下,使用Equals进行等式检查,并在sorting时进行比较,然后为作业select正确的StringComparison。
迈克尔·卡普兰(Michael Kaplan)(文化和人物处理公认的权威人士)在ToUpper和ToLower上有相关的post:
他说:“String.ToUpper – 使用ToUpper而不是ToLower,并指定InvariantCulture以获取OS套pipe规则 ”
我在我的查询中使用了System.Data.Linq.SqlClient.SqlMethods.Like(row.Name, "test")
。
这将执行不区分大小写的比较。
我试着用Lambdaexpression式,它工作。
List<MyList>.Any (x => (String.Equals(x.Name, name, StringComparison.OrdinalIgnoreCase)) && (x.Type == qbType) );
如果你将一个不区分大小写的string传递给LINQ-to-SQL,它将被传递到SQL中并保持不变,比较将在数据库中进行。 如果要在数据库中执行不区分大小写的string比较,则只需创build一个执行比较的lambdaexpression式,LINQ-to-SQL提供程序就会将该expression式转换为string完整的SQL查询。
例如,这个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"
正如你所看到的,string参数将在SQL中进行比较,这意味着事情应该按照你期望的方式工作。
要执行区分大小写的Linq到Sql查询,通过使用以下命令之一来指定服务器数据types,将“string”字段声明为区分大小写;
varchar(4000) COLLATE SQL_Latin1_General_CP1_CS_AS
要么
nvarchar(Max) COLLATE SQL_Latin1_General_CP1_CS_AS
注意:上述整理types中的“CS”表示“区分大小写”。
当使用Visual Studio DBML Designer查看属性时,可以在“服务器数据types”字段中input该值。
有关更多详情,请参阅http://yourdotnetdesignteam.blogspot.com/2010/06/case-sensitive-linq-to-sql-queries.html
where row.name.StartsWith(q, true, System.Globalization.CultureInfo.CurrentCulture)
以下2阶段方法适用于我(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); }
请记住,查询是否有效以及它是否有效工作是有区别的。 当语句的目标是SQL Server时,将LINQ语句转换为T-SQL,因此您需要考虑将生成的T-SQL。
使用String.Equals将很可能(我猜)从SQL Server带回所有行,然后在.NET中进行比较,因为它是一个.NETexpression式,无法转换为T-SQL。
换句话说,使用expression式会增加您的数据访问并消除使用索引的能力。 它将在小桌子上工作,你不会注意到它们之间的差异。 在一个大桌子上,它可能performance非常糟糕。
这是LINQ存在的问题之一。 人们不再考虑他们所写的陈述将如何实现。
在这种情况下,没有一种方法可以在不使用expression式的情况下执行所需的操作 – 即使在T-SQL中也是如此。 因此,您可能无法更有效地做到这一点。 即使是上面给出的T-SQL答案(使用整理后的variables)也很可能会导致索引被忽略,但如果它是一个大表,那么值得运行这个语句并查看执行计划来查看索引是否被使用。