문자열 컬럼에 대해서도 `>` 또는 `<`와 같은 비교 연산을 할 수 있습니다. 문자열 비교는 기본적으로 알파벳 순서(사전적 순서)에 따라 이루어집니다. 예를 들어 `"apple" < "banana"`는 `true`로 평가됩니다. 이러한 비교는 `string.Compare` 메서드를 사용하거나 기본 `Expression.GreaterThan` 또는 `Expression.LessThan`을 이용할 수 있습니다.
다음은 문자열 컬럼을 포함한 비교 예제를 보여줍니다.
### 예시 코드:
```csharp
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Collections.Generic;
public class Program
{
public class Item
{
public int Value1 { get; set; }
public int Value2 { get; set; }
public string Name { get; set; } // 문자열 컬럼 추가
}
public static void Main()
{
var items = new List<Item>
{
new Item { Value1 = 5, Value2 = 10, Name = "apple" },
new Item { Value1 = 10, Value2 = 15, Name = "banana" },
new Item { Value1 = 20, Value2 = 25, Name = "cherry" }
};
// 각 컬럼에 대해 비교할 조건 (문자열 포함)
var conditions = new List<(string PropertyName, string Operator, object Value)>
{
("Value1", ">", 5),
("Value2", "<=", 20),
("Name", "<", "cherry") // 문자열 비교
};
// 조건을 결합한 Expression을 생성
var predicate = BuildDynamicQuery<Item>(conditions);
// LINQ 쿼리 실행
var filteredItems = items.AsQueryable().Where(predicate).ToList();
// 필터링된 결과 출력
foreach (var item in filteredItems)
{
Console.WriteLine($"Value1: {item.Value1}, Value2: {item.Value2}, Name: {item.Name}");
}
}
public static Expression<Func<T, bool>> BuildDynamicQuery<T>(List<(string PropertyName, string Operator, object Value)> conditions)
{
// 매개 변수
var parameter = Expression.Parameter(typeof(T), "x");
// 조건들을 결합한 Expression을 생성
Expression body = null;
foreach (var condition in conditions)
{
var member = Expression.Property(parameter, condition.PropertyName);
var constant = Expression.Constant(condition.Value);
Expression comparison;
// 문자열인지 확인
if (member.Type == typeof(string))
{
// 문자열 비교 연산을 처리하기 위해 string.Compare 메서드 사용
var compareMethod = typeof(string).GetMethod("Compare", new[] { typeof(string), typeof(string) });
var compareExpression = Expression.Call(null, compareMethod, member, constant);
comparison = condition.Operator switch
{
"=" => Expression.Equal(member, constant),
">" => Expression.GreaterThan(compareExpression, Expression.Constant(0)),
"<" => Expression.LessThan(compareExpression, Expression.Constant(0)),
">=" => Expression.GreaterThanOrEqual(compareExpression, Expression.Constant(0)),
"<=" => Expression.LessThanOrEqual(compareExpression, Expression.Constant(0)),
"!=" => Expression.NotEqual(member, constant),
_ => throw new NotSupportedException($"Unsupported operator: {condition.Operator}")
};
}
else
{
// 문자열이 아닌 경우 기본 연산자 사용
comparison = condition.Operator switch
{
"=" => Expression.Equal(member, constant),
">" => Expression.GreaterThan(member, constant),
"<" => Expression.LessThan(member, constant),
">=" => Expression.GreaterThanOrEqual(member, constant),
"<=" => Expression.LessThanOrEqual(member, constant),
"!=" => Expression.NotEqual(member, constant),
_ => throw new NotSupportedException($"Unsupported operator: {condition.Operator}")
};
}
// 조건들을 And로 결합
body = body == null ? comparison : Expression.AndAlso(body, comparison);
}
// 최종 Expression 생성
return Expression.Lambda<Func<T, bool>>(body, parameter);
}
}
```
### 코드 설명:
1. **`BuildDynamicQuery<T>` 함수에서 문자열 처리 추가**:
- 문자열 컬럼을 비교할 때 `string.Compare` 메서드를 사용합니다. `string.Compare`는 두 문자열을 비교하여 음수, 0, 양수를 반환하는 메서드입니다. 이를 통해 `>` 또는 `<` 같은 비교가 가능합니다.
- `Expression.Call`을 사용하여 `string.Compare` 메서드를 호출하는 식을 만듭니다. 그리고 반환된 값이 0보다 크거나 작은지를 비교하여 `GreaterThan` 또는 `LessThan` 등의 연산을 수행합니다.
2. **문자열 비교 예시**:
- 예를 들어 `"Name < 'cherry'"` 조건은 사전적 순서로 `"Name"`이 `"cherry"`보다 앞에 있는 문자열을 필터링합니다.
- 이 외에도 `>` 연산자 등 다른 비교 연산자도 유사한 방식으로 처리됩니다.
3. **다양한 데이터 타입 처리**:
- 코드에서 문자열인지 여부를 확인한 후 해당 데이터 타입에 맞는 비교식을 생성합니다. 숫자 및 기타 기본 타입에 대해서는 기존처럼 `Expression.GreaterThan` 등으로 처리하고, 문자열에 대해서만 `string.Compare`를 사용합니다.
### 실행 결과:
이 예제에서는 `Value1 > 5`, `Value2 <= 20`, 그리고 `Name < "cherry"` 조건이 모두 만족하는 항목들만 필터링됩니다.
### 결론:
이 방식으로 숫자 컬럼뿐만 아니라 문자열 컬럼에 대해서도 동적으로 부등호 비교를 수행할 수 있습니다. `Expression` 트리를 활용하여 각 데이터 타입에 맞는 비교식을 생성하는 유연한 방법을 사용할 수 있습니다.
카테고리 없음