Buscar MySQL con distinción entre mayúsculas y minúsculas en Entity Framework

La abstracción de alto nivel proporcionada por Entity Framework a veces desafía a los desarrolladores a acceder al conjunto completo de funciones disponibles a través del SQL nativo de un servidor de base de datos en particular. Este artículo lo ayudará a lidiar con el uso de la asignación en MySQL para controlar la configuración de distinción entre mayúsculas y minúsculas en las consultas generadas.

La colación determina el orden mediante el proceso de comparar dos cadenas de caracteres dadas y decidir cuál debe ser la anterior.

La documentación del servidor MySQL dice:

«Para cadenas no binarias (CHAR, VARCHAR, TEXT), la búsqueda de cadenas utiliza la coincidencia de operandos de comparación. Para cadenas binarias (BINARY, VARBINARY, BLOB) en comparación use valores numéricos de bytes en operandos; esto significa que para los caracteres alfabéticos la comparación distinguirá entre mayúsculas y minúsculas.
El conjunto de caracteres y el cálculo predeterminados son latin1 y latin1_swedish_ci, por lo que la comparación de las cadenas no binarias se establece de forma predeterminada en mayúsculas y minúsculas.

Hay dos formas alternativas de hacer que la búsqueda distinga entre mayúsculas y minúsculas:

  • uno de los operandos tiene un registro o mapeo binario (por ejemplo: se puede establecer a través de COLLATE en la declaración de la columna)
  • el operador COLLATE se utiliza en la operación de comparación

La implementación de Entity Framework en dotConnect para MySQL incluye las siguientes características:

  • Método MySqlFunctions.Collate para incluir la declaración COLLATE con la colección requerida en el SQL generado
  • El parámetro config.QueryOptions.ComparisonCollation para usar la instrucción COLLATE con la colección requerida al comparar cadenas en casos "iguales" y "no iguales".
  • El parámetro config.QueryOptions.LikeCollation para usar la instrucción COLLATE con la colección especificada para los métodos .Contains / .StartsWith / .EndsWith

Aquí hay un ejemplo.

CREATE TABLE DEPT (
  DEPTNO INT PRIMARY KEY,
  DNAME VARCHAR(14),
  LOC VARCHAR(13)
);
INSERT INTO DEPT VALUES (10,'New Department','Seattle');
INSERT INTO DEPT VALUES (11,'NEW DEPARTMENT','Seattle');
INSERT INTO DEPT VALUES (12,'new department','Seattle');
SELECT * FROM DEPT WHERE DNAME LIKE 'n%'

devuelve 3 lineas

SELECT * FROM DEPT WHERE DNAME COLLATE latin1_bin LIKE 'n%'

devuelve 1 línea

SELECT * FROM DEPT WHERE DNAME COLLATE latin1_bin LIKE 'N%'

devuelve 2 líneas

Puede utilizar la herramienta dbMonitor para habilitar el seguimiento de la actividad de la base de datos.

Aquí hay un ejemplo que muestra cómo usar MySqlFunctions.Collate con una columna comparada o en .Contains / .StartsWith / .EndsWith localmente (en consultas LINQ individuales):

C #

        var monitor = new Devart.Data.MySql.MySqlMonitor() { IsActive = true };

        using (MyDbContext context = new MyDbContext()) {

            var equals_query = context.Depts.Where(d => MySqlFunctions.Collate(d.DNAME, "latin1_bin") == "New Department");
            var equals_results = equals_query.ToList();

            var not_equals_query = context.Depts.Where(d => MySqlFunctions.Collate(d.DNAME, "latin1_bin") != "New Department");
            var not_equals_results = not_equals_query.ToList();

            var like_query = context.Depts.Where(d => MySqlFunctions.Collate(d.DNAME, "latin1_bin").Contains("New"));
            var like_results = like_query.ToList();
        }

V. B.

        Dim monitor As New Devart.Data.MySql.MySqlMonitor
        monitor.IsActive = True

        Using context As New MyDbContext

            Dim equals_query = context.Depts.Where(Function(d) MySqlFunctions.Collate(d.DNAME, "latin1_bin") = "New Department")
            Dim equals_results = equals_query.ToList()

            Dim not_equals_query = context.Depts.Where(Function(d) MySqlFunctions.Collate(d.DNAME, "latin1_bin")  "New Department")
            Dim not_equals_results = not_equals_query.ToList()

            Dim like_query = context.Depts.Where(Function(d) MySqlFunctions.Collate(d.DNAME, "latin1_bin").Contains("New"))
            Dim like_results = like_query.ToList()

        End Using

Si lo desea, puede configurar la asignación globalmente (en el dominio de aplicación actual):

C #

        var monitor = new Devart.Data.MySql.MySqlMonitor() { IsActive = true };

        var config = Devart.Data.MySql.Entity.Configuration.MySqlEntityProviderConfig.Instance;
        config.QueryOptions.LikeCollation = "latin1_bin";
        config.QueryOptions.ComparisonCollation = "latin1_bin";

        using (MyDbContext context = new MyDbContext()) {

            var equals_query = context.Depts.Where(d => d.DNAME == "New Department");
            var equals_results = equals_query.ToList();

            var not_equals_query = context.Depts.Where(d => d.DNAME != "New Department");
            var not_equals_results = not_equals_query.ToList();

            var like_query = context.Depts.Where(d => d.DNAME.Contains("New"));
            var like_results = like_query.ToList();
        }

V. B.

        Dim monitor As New Devart.Data.MySql.MySqlMonitor
        monitor.IsActive = True

        Dim config = Devart.Data.MySql.Entity.Configuration.MySqlEntityProviderConfig.Instance
        config.QueryOptions.LikeCollation = "latin1_bin"
        config.QueryOptions.ComparisonCollation = "latin1_bin"

        Using context As New MyDbContext

            Dim equals_query = context.Depts.Where(Function(d) d.DNAME = "New Department")
            Dim equals_results = equals_query.ToList()

            Dim not_equals_query = context.Depts.Where(Function(d) d.DNAME  "New Department")
            Dim not_equals_results = not_equals_query.ToList()

            Dim like_query = context.Depts.Where(Function(d) d.DNAME.Contains("New"))
            Dim like_results = like_query.ToList()
        End Using

Artículos de interés

Subir