Seqüência de caracteres insensível comparar em LINQ para SQL

Eu li que é insensato usar ToUpper e ToLower para realizar comparações de cadeias sem distinção entre maiúsculas e minúsculas, mas não vejo alternativa quando se trata de LINQ para SQL. Os argumentos ignoreCase e CompareOptions de String.Compare são ignorados pelo LINQ para SQL (se você estiver usando um database com distinção entre maiúsculas e minúsculas, obterá uma comparação com distinção entre maiúsculas e minúsculas, mesmo se solicitar uma comparação sem distinção entre maiúsculas e minúsculas). É ToLower ou ToUpper a melhor opção aqui? Um é melhor que o outro? Eu achei que li em algum lugar que ToUpper era melhor, mas não sei se isso se aplica aqui. (Estou fazendo muitas revisões de código e todo mundo está usando o ToLower.)

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

Isso se traduz em uma consulta SQL que simplesmente compara row.Name com “teste” e não retornará “Test” e “TEST” em um database com distinção entre maiúsculas e minúsculas.

Como você diz, existem algumas diferenças importantes entre o ToUpper e o ToLower, e apenas um é confiável quando você está tentando realizar verificações de igualdade insensíveis a maiúsculas e minúsculas.

Idealmente, a melhor maneira de fazer uma verificação de igualdade sem distinção entre maiúsculas e minúsculas é:

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

Observe o IgnoreCase ordinal para torná-lo seguro para a segurança. Mas exatamente o tipo de verificação sensível que você usa depende de quais são seus objectives. Mas, em geral, use Equals para verificações de igualdade e Compare quando estiver classificando e, em seguida, escolha a StringComparison correta para o trabalho.

Michael Kaplan (uma autoridade reconhecida em cultura e manipulação de caracteres como essa) tem posts relevantes no ToUpper vs. ToLower:

Ele diz “String.ToUpper – Use ToUpper em vez de ToLower e especifique InvariantCulture para obter as regras de shell do SO

Eu usei System.Data.Linq.SqlClient.SqlMethods.Like(row.Name, "test") na minha consulta.

Isso realiza uma comparação insensível a maiúsculas e minúsculas.

Eu tentei isso usando a expressão Lambda, e funcionou.

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

Se você passar uma string que não diferencia maiúsculas de minúsculas em LINQ para SQL, ela será passada para o SQL inalterada e a comparação ocorrerá no database. Se você quiser fazer comparações de cadeias sem distinção entre maiúsculas e minúsculas no database, tudo o que você precisa fazer é criar uma expressão lambda que faça a comparação e o provedor LINQ para SQL converterá essa expressão em uma consulta SQL com a cadeia intacta.

Por exemplo, esta consulta LINQ:

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

é traduzido para o seguinte SQL pelo provedor LINQ para 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" 

Como você pode ver, o parâmetro string será comparado em SQL, o que significa que as coisas devem funcionar do jeito que você espera.

Para executar consultas Linq a Sql com distinção entre maiúsculas e minúsculas, declare que os campos ‘string’ diferenciam maiúsculas de minúsculas especificando o tipo de dados do servidor usando um dos seguintes;

 varchar(4000) COLLATE SQL_Latin1_General_CP1_CS_AS 

ou

 nvarchar(Max) COLLATE SQL_Latin1_General_CP1_CS_AS 

Nota: O ‘CS’ nos tipos de agrupamento acima significa ‘Sensível a maiúsculas’.

Isso pode ser inserido no campo “Tipo de dados do servidor” ao exibir uma propriedade usando o Visual Studio DBML Designer.

Para mais detalhes, consulte http://yourdotnetdesignteam.blogspot.com/2010/06/case-sensitive-linq-to-sql-queries.html

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

A seguinte abordagem de dois estágios funciona para mim (VS2010, ASP.NET MVC3, SQL Server 2008, Linq para SQL):

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

Às vezes, o valor armazenado no database pode conter espaços, portanto, isso pode falhar

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

Solução para este problema é remover espaço, em seguida, converter o seu caso, em seguida, selecione como este

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

Note neste caso

customname é o valor para corresponder ao valor do database

UsersTBs é class

title é a coluna do database

Lembre-se de que existe uma diferença entre o funcionamento da consulta e o funcionamento eficiente . Uma instrução LINQ é convertida em T-SQL quando o destino da instrução é SQL Server, portanto, é necessário pensar no T-SQL que seria produzido.

Usando String.Equals provavelmente (eu estou adivinhando) traga de volta todas as linhas do SQL Server e então faça a comparação no .NET, porque é uma expressão .NET que não pode ser traduzida em T-SQL.

Em outras palavras, usar uma expressão aumentará seu access a dados e removerá sua capacidade de usar índices. Ele funcionará em pequenas tabelas e você não notará a diferença. Em uma mesa grande, poderia ter um desempenho muito ruim.

Esse é um dos problemas que existe com o LINQ; as pessoas não pensam mais em como as declarações que escrevem serão cumpridas.

Nesse caso, não há como fazer o que você deseja sem usar uma expressão – nem mesmo no T-SQL. Portanto, talvez você não consiga fazer isso de maneira mais eficiente. Mesmo a resposta T-SQL dada acima (usando variables ​​com collation) provavelmente resultará em índices sendo ignorados, mas se for uma tabela grande, então vale a pena executar a instrução e examinar o plano de execução para ver se um índice foi usado .