String.Format con un comodín de SQL que hace que la consulta de Dapper se rompa

c# dapper sql string-formatting

Pregunta

Estoy teniendo un problema extraño con Dapper y el formato de cadenas. Aquí está el código relevante:

string end_wildcard = @"
SELECT * FROM users
WHERE (first_name LIKE CONCAT(@search_term, '%') OR last_name LIKE CONCAT(@search_term, '%'));";

string both_wildcards = @"
SELECT * FROM users
WHERE (first_name LIKE CONCAT('%', @search_term, '%') OR last_name LIKE CONCAT('%', @search_term, '%'));";

string formatted = @"
SELECT * FROM users
WHERE (first_name LIKE {0} OR last_name LIKE {0});";

string use_end_only = @"CONCAT(@search_term, '%')";
string use_both = @"CONCAT('%', @search_term, '%')";

// if true, slower query due to not being able to use indices, but will allow searching inside strings 
bool allow_start_wildcards = false; 

string query = String.Format(formatted, allow_start_wildcards ? use_both : use_end_only);
string term = "blah"; // the term the user searched for

// Using Dapper
db.Query(end_wildcard, new{ search_term = term}); // Works and returns results
db.Query(both_wildcards, new{ search_term = term}); // Works and returns results
db.Query(query, new{ search_term = term}); // Returns nothing

Las primeras dos consultas, donde las declaraciones CONCAT con comodines en ellas se hornean en la cadena, funcionan perfectamente. Sin embargo, si elimino las instrucciones CONCAT e inyecté una u otra usando String.Format, obtengo 0 resultados.

Lo más extraño es que puedo depurarlo, tomar la cadena de consulta real que utiliza, ponerla en MySQL y ejecutarla con un conjunto de parámetros @search_term, y obtener resultados mientras está en pausa. Deja que el código continúe y obtengo 0 resultados. Literalmente, lo único que es diferente es que uno es una cadena precompilada, y el otro utiliza String.Format.

¿Están '@' y '%' considerados caracteres especiales por String.Format, o hay algo más que no veo que ocurra aquí? La cadena formateada es literalmente byte por byte igual a una de las dos cadenas no formateadas, y nuevamente, pegarla en MySQL en realidad da resultados de la cadena formateada. Dapper parece gustarle dos, y no el tercero, incluso cuando es exactamente igual a uno de los dos primeros.

Respuesta aceptada

Indique exactamente cuál es su query y term en el ejemplo que está fallando. No puedo reproducir ningún problema aquí. Si utilizo el código como se publicó, la query es idéntica a end_wildcard , y: funciona bien. En una plataforma de prueba local (con algunos datos inventados), tengo:

connection.Query(end_wildcard, new { search_term = term }).Count().IsEqualTo(2);
connection.Query(both_wildcards, new { search_term = term }).Count().IsEqualTo(3);
connection.Query(query, new { search_term = term }).Count().IsEqualTo(2);

Si está viendo algo diferente, solo puedo concluir que debe estar relacionado con su ejemplo específico.

Pero para ser específico:

¿Están '@' y '%' considerados caracteres especiales por String.Format, o hay algo más que no veo que ocurra aquí?

Nop string.Format solo se preocupa por cosas como {n} (para el entero n ) y {{ / }} (que son secuencias de escape para { y } respectivamente).

Básicamente, me parece poco probable que Dapper esté haciendo algo relacionado con esto, pero sería útil mostrar su query y term exactos, tal como aparecen cuando está fallando .



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué