¿Cómo uso 'Where In' en Dapper?

.net c# dapper orm sql

Pregunta

He estado intentando infructuosamente ahora por un tiempo usar una IEnumerable<string> con una cláusula WHERE IN en Dapper.

En la documentación, dice que IEnumerable<int> es compatible para su uso en WHERE IN pero ni siquiera puedo hacer que funcione.

Dapper allow you to pass in IEnumerable<int> and will automatically parameterize your query.

El mensaje de error que sigo recibiendo es un error de sintaxis Sql. Incorrect syntax near ','.

He creado un código de prueba que espero que demuestre lo que estoy tratando de lograr.


string connString = "Server=*.*.*.*;Database=*;User Id=*;Password=*;";

string sqlStringIn = @"SELECT StringText FROM 
                (SELECT 1 ID, 'A' StringID, 'This is a test' StringText
                UNION SELECT 2 ID, 'B' StringID, 'Another test' StringText
                UNION SELECT 3 ID, 'C' StringID, 'And another' StringText
                UNION SELECT 4 ID, 'D' StringID, 'and again' StringText
                UNION SELECT 5 ID, 'E' StringID, 'yet again' StringText) data
                WHERE StringId IN (@str)";

string sqlIntegerIn = @"SELECT StringText FROM 
                (SELECT 1 ID, 'A' StringID, 'This is a test' StringText
                UNION SELECT 2 ID, 'B' StringID, 'Another test' StringText
                UNION SELECT 3 ID, 'C' StringID, 'And another' StringText
                UNION SELECT 4 ID, 'D' StringID, 'and again' StringText
                UNION SELECT 5 ID, 'E' StringID, 'yet again' StringText) data
                WHERE ID IN (@integer)";


using (SqlConnection conn = new SqlConnection(connString))
{
    conn.Open();

    List<int> integers = new List<int>{ 1, 2, 3 };
    List<string> strings = new List<string> { "A", "B", "C" };

    var parameters = new {str = strings, integer = integers };

    //fails here
    IEnumerable<string> intTest = conn.Query<string>(sqlIntegerIn, parameters, commandType: System.Data.CommandType.Text);

    //and here
    IEnumerable<string> stringTest = conn.Query<string>(sqlStringIn, parameters, commandType: System.Data.CommandType.Text);

}

Respuesta aceptada

Para hacer lo que se necesita aquí, Dapper necesita modificar el SQL sobre la marcha, por lo que debe estar realmente seguro de que está haciendo lo correcto. La sintaxis SQL válida regular incluye paréntesis:

WHERE StringId IN (@str)

Para desambiguar a partir de esto, la sintaxis del vudú omite el paréntesis:

WHERE StringId IN @str

Si detecta esto, busca un parámetro llamado str , y lo expande, a uno de:

WHERE 1=0 -- if no values
WHERE StringId = @str -- if exactly one value
WHERE StringId IN (@str0, @str1, ...) -- if more than one value

Pero versión corta: eliminar el paréntesis.


Respuesta popular

Quiero agregar una nota importante si está interesado en poder manejar una lista vacía, es decir, hacer que la cláusula IN optional . Hice esto agregando una propiedad para contener el recuento como public int InClauseCount => InClauseList?.Length ?? 0;

Luego usa el conteo dentro del sql como este ...

Select field1, field2
from Table1
where (some condition)
AND (@InClauseCount = 0 OR field1 IN @InClauseList)

Espero que esto pueda ayudar a alguien por ahí. Pasé demasiado tiempo tratando de resolver esto, en parte porque soy nuevo en Dapper.



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow