简体   繁体   English

如何使用具有多个属性的集合在 Dapper 中进行过滤?

[英]How to filter in Dapper using a collection with multiple properties?

I am a bit new to Dapper and am trying to find a clean way to pass a filter parameter to SQL Query for a collection with more than one property.我对 Dapper 有点陌生,正在尝试找到一种干净的方法将过滤器参数传递给 SQL Query 以获取具有多个属性的集合。

My collection looks like this:我的收藏是这样的:

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

Which should result in a SQL Query looking something like this:这应该导致 SQL 查询看起来像这样:

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

Note: Something like whats shown below will not work because the two properties PropA and PropB need to filter together.注意:下面显示的内容将不起作用,因为两个属性 PropA 和 PropB 需要一起过滤。

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();

You can generate filter strings dynamically using the following helper class:您可以使用以下帮助程序类动态生成过滤器字符串:

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));
        }
    }

Usage:用法:

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();

Query string looks like:查询字符串如下所示:

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

Modeling your filters as a class:将过滤器建模为一个类:

class MyFilterDefinition
{
    public string Prop1 { get; set; }
    public string Prop2 { get; set; }
}

Build that dynamic condition using DapperQueryBuilder would be as simple as this:使用DapperQueryBuilder构建动态条件就像这样简单:

var myOptions = new List<MyFilterDefinition>()
{
    new MyFilterDefinition() { Prop1 = "A Value 1", Prop2 = "B Value 1" },
    new MyFilterDefinition() { Prop1 = "A Value 2", Prop2 = "B Value 2" }
}

var query = cn.QueryBuilder($@"
    select *
    from SampleTable
    /**where**/");

// by default multiple filters are combined with AND, so change to OR
query.FiltersType = Filters.FiltersType.OR; 

foreach (var option in myOptions)
    query.Where($"[ColumnA] = {option.Prop1} AND [ColumnB] = {option.Prop2}");

var results = query.Query<YourPOCO>();

The final result would be this:最终的结果是这样的:

    select *
    from SampleTable
    where ([ColumnA]=@p0 AND [ColumnB]=@p1) OR ([ColumnA]=@p2 AND [ColumnB]=@p3)

With the respective parameters @p0 = 'A Value 1', etc..使用各自的参数@p0 = 'A Value 1',等等。

Disclaimer: I'm the author of DapperQueryBuilder免责声明:我是 DapperQueryBuilder 的作者

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM