2017-10-19 3 views
2

Dapper를 처음 접했을 때 둘 이상의 속성이있는 컬렉션에 대해 SQL 쿼리에 필터 매개 변수를 전달하는 명확한 방법을 찾으려고합니다.여러 속성이있는 컬렉션을 사용하여 Dapper를 필터링하는 방법은 무엇입니까?

는 내 컬렉션은 다음과 같습니다과 같은 SQL 쿼리보고 뭔가 발생한다

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

:

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

참고 : 작동하지 않습니다 아래 뭐죠 비슷해 두 속성 때문에 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(); 

답변

0
당신은 동적으로 다음과 같은 헬퍼 클래스를 사용하여 필터 문자열을 생성 할 수 있습니다

:

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

사용법 :

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

쿼리 문자열 보이는 같은 :

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

덕분에 나는이 생각을 정말 도움이됩니다. Dapper의 솔루션은 아니지만 재사용이 가능하고 좋은 솔루션입니다. 이 솔루션을 염두에 두어야 할 또 다른 사항은 매개 변수를 전달하는 기본 Dapper 메서드를 사용하지 않기 때문에 SQL 삽입을 확인하는 것입니다. – m0g

+0

그래, 내 솔루션은 단지 SQL 주입과 같은 다른 특권을 고려하지 않고 필터 문자열을 구성하는 방법을 보여줍니다. – Yared

+0

이 링크는 도움이 될 수도 있습니다. https://github.com/tmsmith/Dapper-Extensions/wiki/Predicates '복합 복합어 (조건부 그룹)'섹션을 참조하십시오. – Yared