Cómo filtrar en Dapper utilizando una colección con múltiples propiedades?

.net-core c# dapper

Pregunta

Soy un poco nuevo en Dapper y estoy tratando de encontrar una forma limpia de pasar un parámetro de filtro a SQL Query para una colección con más de una propiedad.

Mi colección se ve así:

[{
    Prop1: 'A Value 1',
    Prop2: 'B Value 1'
},
{
    Prop1: 'A Value 2',
    Prop2: 'B Value 2'
}]

Lo cual debería dar como resultado que una consulta SQL tenga un aspecto similar a este:

select *
from SampleTable
where
([ColumnA]='A Value 1' and [ColumnB]='B Value 1')
or ([ColumnA]='A Value 2' and [ColumnB]='B Value 2')

Nota: algo como lo que se muestra a continuación no funcionará porque las dos propiedades PropA y PropB deben filtrarse juntas.

string query = @"select *
                from SampleTable
                where [ColumnA] in (@PropA_Value)
                and [ColumnB] in (@PropB_Value)"

con.Query<T>(query, new{PropA_Value = PropA,PropB_Value = PropB}).AsList();

Respuesta popular

Puede generar cadenas de filtro dinámicamente utilizando la siguiente clase de ayuda:

public static class DapperHelper
    {
        private const string SingleTupleFormat = " [{0}] = '{1}' {2}";
        private const string AndString = "AND";
        private const string OrString = "OR";

        private static string ToSqlTuple(List<Dictionary<string, string>> filters) 
        {
             string filterParam = string.Empty;
             foreach (var filter in filters)
             {
                 //Construct single tuple
                 string tuple = filter.ToList().Aggregate(string.Empty,
                 (current, pair) => current + String.Format(SingleTupleFormat, pair.Key, pair.Value, AndString));

                 //Concatenate tuples by OR, string.Format to combine the different filters
                 filterParam += string.Format(" ({0}) {1}", tuple.TrimEnd(AndString), OrString);
             }
             return filterParam.TrimEnd(OrString);
         }

        public static string TrimEnd(this string source, string value)
        {
            if (!source.EndsWith(value))
                return source;

            return source.Remove(source.LastIndexOf(value));
        }
    }

Uso:

string query = @"select *
                from SampleTable
                where @where";

List<Dictionary<string, string>> filters = new List<Dictionary<string, string>>() {
                new Dictionary<string, string>(){{"ColumnA", "A Value 1"},{"ColumnB", "A Value 2"}},
                new Dictionary<string, string>(){{"ColumnA", "B Value 1"},{"ColumnB", "B Value 2"}}
            };

var tuple = DapperHelper.ToSqlTuple(filters);
query = query.Replace("@where", string.IsNullOrEmpty(tuple) ? "1=1" : tuple); //Use 1=1 if tuple is empty or null

var data = con.Query<T>(query).AsList();

La cadena de consulta se ve así:

select *
from SampleTable
where  ( [ColumnA] = 'A Value 1' AND [ColumnB] = 'A Value 2' ) 
    OR ( [ColumnA] = 'B Value 1' AND [ColumnB] = 'B Value 2' )


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é