我已经读到,使用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"。
- 谢谢!今天真的救了我一命。注:它也适用于其他LINQ扩展,如LINQQuery.Contains("VaLuE", StringComparer.CurrentCultureIgnoreCase)和LINQQuery.Except(new string[]{"A VaLUE","AnOTher VaLUE"}, StringComparer.CurrentCultureIgnoreCase)。哇!
- 有趣的是,我刚刚读到,toupper在这个来源的比较上更好:msdn.microsoft.com/en-us/library/dd465121
正如你所说,toupper和tolower之间有一些重要的区别,当你试图进行不区分大小写的平等检查时,只有一个是可靠准确的。
理想情况下,进行不区分大小写的相等检查的最佳方法是:
1
| String.Equals(ROW.Name,"test", StringComparison.OrdinalIgnoreCase) |
但是请注意,在这种情况下这不起作用!因此,我们只能使用ToUpper或ToLower。
注意顺序案例以确保安全。但是,您使用的区分大小写检查的具体类型取决于您的目的。但是,通常在排序时使用equals进行相等性检查和比较,然后为作业选择正确的StringComparison。
迈克尔·卡普兰(一位公认的文化和性格处理权威,如此)在《图珀与托洛威尔》中有相关的职位:
- http://www.siao2.com/2007/10/01/5218976.aspx
- http://www.siao2.com/2005/03/10/391564.aspx
他说:"string.toupper–使用toupper而不是tolower,并指定不变的区域性以获取操作系统的大小写规则。"
- 这似乎不适用于SQL Server:print upper('gro&223;e stra&223;e')返回gro&223;e stra&223;e
- 另外,您提供的示例代码与我提供的代码有相同的问题,在通过Linq to SQL在MS SQL 2005数据库上运行时,代码区分大小写。
- 我同意。对不起,我不清楚。正如您在原始问题中指出的,我提供的示例代码不适用于linq2sql。我只是重申一下,你开始的方式是一个很好的方式,如果它只在这个场景中起作用的话。是的,另一个Mike Kaplan Soapbox是SQL Server的字符处理无处不在。如果您需要不区分大小写,并且不能以任何其他方式获得它,我建议(不清楚地)将数据存储为大写,然后以大写形式进行查询。
- …也就是说,在.NET中进行大小写转换,并将转换后的字符串传递给SQL,用于存储和查询。
- 在SQL Server中执行upper(在.NET中使用toupper,并让它在SQL中转换为upper())并比较结果有什么问题吗?我不希望所有的数据总是以大写形式出现,只是为了在数据库中强制执行不区分大小写的比较,老实说,这很可能是不区分大小写的;我只希望在不区分大小写的情况下,将此逻辑放在适当的位置。此外,在这种情况下,上下之间是否存在显著差异?(您可以提供任何演示?)
- 我认为,如果您同时调用upper()for SQL来存储和查询,那么您可能还可以。虽然所有字符都有大写表示,但并不是所有的Unicode字符都有小写等价物,所以我会避开小写字符。我不知道这样一个例子,但迈克尔·卡普兰谈到了他们。
- 我们不会调用to upper或tolower来存储数据,因为我们不希望所有数据总是以大写显示,而是希望保留混合大小写数据显示。这是个问题吗?
- 我不理解使用upper()存储数据的建议。为什么在检索数据时不能使用upper()?
- 好吧,如果您有一个区分大小写的数据库,并且您存储在混合大小写中,并在大写中搜索,那么您将不会得到匹配项。如果您在搜索中同时对数据和查询进行大写,那么您将为每个查询转换要搜索的所有文本,而这些文本并没有执行。
- 我看到执行计划的一些有趣结果。当我执行语句"select*from oitm where upper(itemcode)='23-red'"时,我看到执行计划正在执行索引扫描、键查找和嵌套循环,由于某种原因,只要执行非常类似的"select*from oitm where upper(itemcode)='19-black'"时,执行计划就只需要14%的聚集索引扫描(单独进行)。
- @BlueMonkmn,您确定粘贴了正确的代码片段吗?很难相信MSSQL服务器更喜欢红色而不是黑色。
- 我也无法解释。可能是因为字符串的长度达到了某个阈值,或者是因为特定表中不同值背后的统计数据,或者是因为19-black是第一行的值——谁知道呢。
- 我试过你说的,我遇到了这个问题:stackoverflow.com/questions/5080727/…
- 对于任何从搜索中来到这里的人来说,帖子中的链接都是死的,但是仍然可以通过archive.org:web.archive.org/web/20130723203412/http://blogs.msdn.com/b/&hellip访问。
- 为什么标记为正确答案?这不是问题的答案,它只是让很多人困惑,因为这不适用于linq2sql。
- @阿尔伯特蒙蒂亚诺你为什么说这不是问题的答案?问到的问题是"托洛威尔或托普是这里最好的选择吗?"一个比另一个好吗?"我的帖子回应说,笨蛋更好。并解释了一系列相关数据。
- 您好@andrewarnott,此问题的上下文是linq to sql,您提出的最佳方式来进行不区分大小写的相等性检查不适用于此。我认为问题在于如何在LINQ和SQL中进行比较,不管这之外还有什么其他方法。
- @你为什么接受这个答案?我认为这是Linq to SQL的正确答案。这绝对是个错误的错误答案。它不适用于Linq to SQL。如果你仍然认为这是一个正确的答案,请改变你的问题,使它不会出现在谷歌搜索。谢谢。。。。
- @除了问题中提出的答案(touppet),没有正确的答案,这就是这个答案所证实的,如果你阅读前3条评论,你就会明白。这是唯一一个证实了我们的愿望和我们所坚持的答案。
- @在这种情况下,安德鲁应该改变他的答案。因为这是错误的。或者你应该把你自己的答案贴出来并标记为答案。当我点击谷歌搜索时,人们会立即看到被接受的答案。我怀疑是否有人会在代码因为错误的答案而崩溃之前查看注释。这绝对是误导。也许,(以最谦虚的方式——我求求你)是改变你的问题,这样它就不会出现在谷歌搜索上。现在,它正处于谷歌搜索的顶端,在谷歌搜索中,答案是绝对的,绝对的,不可否认的错误…
- @山姆,对于母语不是英语的人(或不仔细阅读的人),这可能看起来是一个错误的答案,但如果你仔细阅读,声明说"理想情况下,进行不区分大小写的平等检查的最佳方法是:"等等…,这意味着这不是实际的答案。但我同意这可能会产生误导。我将编辑答案,使其更加明显。如果更新的答案(给我5分钟)看起来更好,请告诉我。
- @Bluemonkmn,你问的是Case insensitive string compare in LINQ-to-SQL。它不需要一个英语母语的人来理解这个问题是关于linq-to-sql中的字符串比较。感谢您编辑答案。但我仍然希望它不会突出显示String.Equals(row.Name,"test", StringComparison.OrdinalIgnoreCase),因为它在linq-to-sql中不起作用。
我用过System.Data.Linq.SqlClient.SqlMethods.Like(row.Name,"test")在我的询问中。
这将执行不区分大小写的比较。
- 哈!已经使用Linq2SQL好几年了,但直到现在还没有看到SQLMethods,谢谢!
- 精彩!不过,可能需要更多细节。这是like的预期用途之一吗?是否有可能导致假阳性结果的输入?还是一个错误的否定结果?关于这个方法的文档是缺乏的,描述类似方法操作的文档在哪里?
- 我认为它仅仅依赖于SQL Server如何比较字符串,而字符串可能在某个地方是可配置的。
- system.data.linq.sqlclient.sqlmethods.like(row.name,"test")与row.name.contains("test")相同。正如安德鲁所说,这取决于SQL Server的排序规则。所以like(或contains)并不总是执行不区分大小写的比较。
- 请注意,这使得代码与SqlClient过于耦合。
- 这个答案应该被接受,因为它是基于问题的正确答案。
我用lambda表达式尝试了这个方法,它起作用了。
List.Any (x => (String.Equals(x.Name, name, StringComparison.OrdinalIgnoreCase)) && (x.Type == qbType) );
- 这是因为您使用的是List<>,这意味着比较是在内存(C代码)中进行的,而不是在数据库中执行比较的IQueryable或ObjectQuery。
- 什么@drzaus说。考虑到上下文是linq2sql,而不是常规的linq,这个答案是完全错误的。
有时存储在数据库中的值可能包含空格,因此运行该值可能会失败。
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) |
- 将其翻译成什么样的SQL文本,以及在其他情况下将其视为区分大小写的SQL环境中,什么允许它不区分大小写?
以下两阶段方法适用于我(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);
} |
- 如果文本以搜索文本开头,则此代码有错误(应大于等于0)
- @flatlinerdoa实际上应该是!= -1,因为IndexOf"如果找不到字符或字符串,则返回-1"
要执行区分大小写的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。
- 这就是问题所在。通常我使用的领域是区分大小写的(化学式一氧化碳不同于钴)。但是,在特定情况下(搜索),我希望CO同时匹配CO和CO。用不同的"服务器数据类型"定义其他属性是不合法的(Linq to SQL只允许每个SQL列有一个属性)。所以还是不去。
- 此外,如果进行单元测试,这种方法可能与数据模拟不兼容。最好在接受的答案中使用linq/lambda方法。
如果将不区分大小写的字符串传递给Linq to SQL,它将以不变的方式传递给SQL,并在数据库中进行比较。如果要在数据库中进行不区分大小写的字符串比较,只需创建一个进行比较的lambda表达式,Linq to SQL提供程序会将该表达式转换为字符串完整的SQL查询。
例如,此Linq查询:
由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中进行比较,这意味着事情应该按照预期的方式进行。
- 我不明白你在说什么。1)字符串本身在.NET中不能区分大小写,因此不能传递"不区分大小写的字符串"。2)LINQ查询基本上是一个lambda表达式,这就是我传递两个字符串的方式,所以这对我来说没有任何意义。
- 我想对区分大小写的数据库执行不区分大小写的比较。
- 您使用的是什么区分大小写的数据库?
- 此外,LINQ查询不是lambda表达式。LINQ查询由几个部分组成(最显著的是查询运算符和lambda表达式)。
- MS SQL Server 2005
- 这个答案和BlueMonkmn的评论不一样。
请记住,查询是否有效与查询是否有效之间存在差异!当语句的目标是SQL Server时,LINQ语句将转换为T-SQL,因此需要考虑将生成的T-SQL。
使用string.equals将很可能(我猜)从SQL Server返回所有行,然后在.NET中进行比较,因为它是一个不能转换为T-SQL的.NET表达式。
换句话说,使用表达式将增加您的数据访问量,并删除您使用索引的能力。它适用于小桌子,你不会注意到不同之处。在一张大桌子上,它的性能可能很差。
这是Linq存在的问题之一;人们不再考虑他们所写的语句将如何实现。
在这种情况下,没有一种方法可以不使用表达式就完成您想要的工作,即使在T-SQL中也不行。因此,您可能无法更有效地执行此操作。即使上面给出的T-SQL答案(使用带有排序规则的变量)也很可能导致索引被忽略,但是如果它是一个大表,那么运行该语句并查看执行计划以查看是否使用了索引是值得的。
- 这不是真的(它不会导致行返回到客户机)。我使用了string.equals,它不起作用的原因是它被转换为TSQL字符串比较,其行为取决于数据库或服务器的排序规则。首先,我要考虑如何将我编写的每个LINQ to SQL表达式转换为TSQL。我想要的方法是使用to upper强制生成的TSQL使用upper。然后所有的转换和比较逻辑仍然在TSQL中完成,因此不会损失太多性能。