LINQ donde se ignora la acentuación y el caso

¿Cuál es la forma más fácil de filtrar elementos con LINQ a través del método Where ignorando la acentuación y el caso?

Hasta ahora, he podido ignorar Casing llamando a métodos en las propiedades, lo cual no creo que sea una buena idea porque llama al mismo método para cada elemento (¿no?).

Así que esto es lo que obtuve hasta ahora:

 var result = from p in People where p.Name.ToUpper().Contains(filter.ToUpper()) select p; 

Por favor dígame si esta es una buena práctica y la forma más fácil de ignorar la acentuación.

Para ignorar mayúsculas y minúsculas (signos diacríticos), primero puede definir un método de extensión como este:

  public static string RemoveDiacritics(this String s) { String normalizedString = s.Normalize(NormalizationForm.FormD); StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < normalizedString.Length; i++) { Char c = normalizedString[i]; if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark) stringBuilder.Append(c); } return stringBuilder.ToString(); } 

(Modificado desde Ignorar letras acentuadas en la comparación de cadenas )

Ahora puede ejecutar su consulta:

 string queryText = filter.ToUpper().RemoveDiacritics(); var result = from p in People where p.Name.ToUpper().RemoveDiacritics() == queryText select p; 

Esto está bien si solo está iterando sobre una colección en C #, pero si está utilizando LINQ to SQL es preferible evitar métodos no estándar (incluidos los métodos de extensión) en su consulta LINQ. Esto se debe a que su código no se puede convertir en SQL válido y, por lo tanto, se ejecuta en SQL Server con toda su encantadora optimización del rendimiento.

Dado que no parece haber una forma estándar de ignorar acentos dentro de LINQ a SQL, en este caso sugiero cambiar el tipo de campo que desea buscar para que sea insensible a mayúsculas y minúsculas (CI_AI).

Con tu ejemplo:

 ALTER TABLE People ALTER COLUMN Name [varchar](100) COLLATE SQL_Latin1_General_CP1_CI_AI 

Su consulta ahora debería ignorar la acentuación y el caso.

Tenga en cuenta que deberá eliminar temporalmente cualquier restricción única en el campo antes de ejecutar la consulta anterior, por ejemplo

 ALTER TABLE People DROP CONSTRAINT UQ_People_Name 

Ahora su consulta LINQ sería simplemente:

 var result = from p in People where p.Name == filter select p; 

Vea la pregunta relacionada aquí .

Cambio de clasificación:

 ALTER TABLE dbo.MyTable ALTER COLUMN CharCol varchar(10)**COLLATE Latin1_General_CI_AS** NOT NULL; 

Aquí hay un código que permite la comparación ignorando la acentuación:

Ignorar letras acentuadas en la comparación de cadenas

Tendré la decencia de no copiar el código, para que el autor pueda obtener un representante por su respuesta. Ahora, respondiendo tu pregunta:

Obtendrás ese fragmento de código y lo usarás así:

 var result = from p in People where p.Name.ToUpper().Contains(RemoveDiacritics(filter.ToUpper())) select p; 

Incluso conviertes ese código en un método de extensión. Yo tengo 🙂

Siguiendo la solución de Dunc de cambiar la recostackción de toda la base de datos, aquí hay un tutorial completo que trata con índices, claves, etc.

https://www.codeproject.com/Articles/302405/The-Easy-way-of-changing-Collation-of-all-Database

(Solo asegúrate de leer todos los comentarios primero).