dynamic linq 는 동적 쿼리를 동적 문자열로 처리할 수 있도록 해줍니다.
아래처럼 Linq 식을 보통 사용하게 되지만
var result = context.Customers
.Where(c => c.City == "Paris")
.ToList();
dynamic linq 를 이용하면 아래처럼 사용할 수 있습니다.
var resultDynamic = context.Customers
.Where("City == \"Paris\"")
.ToList();
사용하기 위해선 System.Linq.Dynamic.Core Nuget package 를 설치합니다.
아래는 TestData Class 를 정의하여 사용하는 방법의 예시입니다.
public class TestData
{
public string Name { get; set; }
public int Age { get; set; }
public string Data1 { get; set; }
public string Data2 { get; set; }
public int intData1 { get; set; }
public int intData2 { get; set; }
}
List<TestData> testDataList = new List<TestData>();
// 사용 예시
var queryableData = testDataList.AsQueryable();
var where = queryableData.Where("Name == @0", "NAME0").ToList();
var avg = queryableData.Aggregate("Average", "intData1");
var and = queryableData.Where("Name == @0 and intData1 > @1", "NAME0", 3).ToList();
var select = queryableData.Select("new { Name, Data1 }").ToDynamicList();
var orderedDynamic = queryableData.OrderBy("Name, intData2").ToList();
동적 문자열로 쿼리가 가능해 다양한 조합의 쿼리식을 처리할 수 있습니다.
GroupBy 도 아래처럼 처리할 수 있습니다.
List<dynamic> testDynamicList = new List<dynamic>();
var queryableData = testDynamicList.AsQueryable();
// 싱글 컬럼 GroupBy
var onColumnGroups = queryableData.GroupBy("Name");
foreach (IGrouping<object, object> group in onColumnGroups)
{
string Key = group.Key.ToString();
var dataList = group.ToList();
Console.WriteLine($"{Key} : {dataList.Count()}");
}
// 멀티 컬럼 GroupBy
var multiColumnGroups = queryableData.GroupBy("new (Name as Name, Data1 as Data1)");
foreach (IGrouping<object, object> group in multiColumnGroups)
{
string Key = group.Key.ToString();
var dataList = group.ToList();
Console.WriteLine($"{Key} : {dataList.Count()}");
}
// 멀티 컬럼 GroupBy + 키값 및 키별 Count
var gResult = queryableData.GroupBy("new (Name as Name, Data1 as Data1)").Select("new(Key, Count() AS Count)");
foreach (dynamic result in gResult)
{
Console.WriteLine($"{result.Key} : {result.Count}");
}
// 멀티 컬럼 GroupBy + 특정 컬럼만 선택
var multiColumnGroupsResult = queryableData.GroupBy("new (Name as Name, Data1 as Data1)", "new (Data2 as Data2, intData2 as intData2)");
foreach (IGrouping<object, object> group in multiColumnGroupsResult)
{
Console.WriteLine($"{group.Key} : {group.Count()}");
}
또한 DynamicClass 를 정의하여 사용할 수도 있습니다.
DynamicProperty[] props = new DynamicProperty[]
{
new DynamicProperty("Name", typeof(string)),
new DynamicProperty("Birthday", typeof(DateTime))
};
Type type = DynamicClassFactory.CreateType(props);
object obj = Activator.CreateInstance(type);
type.GetProperty("Name").SetValue(obj, "kei", null);
type.GetProperty("Birthday").SetValue(obj, new DateTime(1995, 3, 14), null);
Console.WriteLine(obj);
전체 코드
using System.Linq.Dynamic.Core;
namespace DynamicLinqTest
{
internal class Program
{
List<dynamic> testDynamicList = new List<dynamic>();
List<TestData> testDataList = new List<TestData>();
static void Main(string[] args)
{
Program program = new Program();
program.SampleData(100);
program.DynamicClass();
program.BasicQuery();
program.GroupBy();
program.Expression();
}
private void SampleData(int count)
{
for (int i = 0; i < count; i++)
{
TestData testData = new TestData()
{
Name = "NAME" + (i / 10),
Age = i,
Data1 = "Data1_" + (i / 5),
Data2 = "Data2_" + i,
intData1 = i + 1,
intData2 = count - i,
};
testDynamicList.Add(testData);
testDataList.Add(testData);
}
}
private void DynamicClass()
{
DynamicProperty[] props = new DynamicProperty[]
{
new DynamicProperty("Name", typeof(string)),
new DynamicProperty("Birthday", typeof(DateTime))
};
Type type = DynamicClassFactory.CreateType(props);
object obj = Activator.CreateInstance(type);
type.GetProperty("Name").SetValue(obj, "kei", null);
type.GetProperty("Birthday").SetValue(obj, new DateTime(1995, 3, 14), null);
Console.WriteLine(obj);
}
private void BasicQuery()
{
var queryableData = testDataList.AsQueryable();
var where = queryableData.Where("Name == @0", "NAME0").ToList();
var avg = queryableData.Aggregate("Average", "intData1");
var and = queryableData.Where("Name == @0 and intData1 > @1", "NAME0", 3).ToList();
var select = queryableData.Select("new { Name, Data1 }").ToDynamicList();
var orderedDynamic = queryableData.OrderBy("Name, intData2").ToList();
}
private void GroupBy()
{
var queryableData = testDynamicList.AsQueryable();
// 싱글 컬럼 GroupBy
var onColumnGroups = queryableData.GroupBy("Name");
foreach (IGrouping<object, object> group in onColumnGroups)
{
string Key = group.Key.ToString();
var dataList = group.ToList();
Console.WriteLine($"{Key} : {dataList.Count()}");
}
// 멀티 컬럼 GroupBy
var multiColumnGroups = queryableData.GroupBy("new (Name as Name, Data1 as Data1)");
foreach (IGrouping<object, object> group in multiColumnGroups)
{
string Key = group.Key.ToString();
var dataList = group.ToList();
Console.WriteLine($"{Key} : {dataList.Count()}");
}
// 멀티 컬럼 GroupBy + 키값 및 키별 Count
var gResult = queryableData.GroupBy("new (Name as Name, Data1 as Data1)").Select("new(Key, Count() AS Count)");
foreach (dynamic result in gResult)
{
Console.WriteLine($"{result.Key} : {result.Count}");
}
// 멀티 컬럼 GroupBy + 특정 컬럼만 선택
var multiColumnGroupsResult = queryableData.GroupBy("new (Name as Name, Data1 as Data1)", "new (Data2 as Data2, intData2 as intData2)");
foreach (IGrouping<object, object> group in multiColumnGroupsResult)
{
Console.WriteLine($"{group.Key} : {group.Count()}");
}
}
private void Expression()
{
var rangeOfNumbers = Enumerable.Range(1, 100).ToArray();
var result1 = rangeOfNumbers.AsQueryable().Where("it in (1,3,5,7, 101)").ToArray();
var values = new int[] { 2, 4, 6, 8, 102 };
var result2 = rangeOfNumbers.AsQueryable().Where("it in @0", values).ToArray();
var result3 = rangeOfNumbers.AsQueryable().Where("it % 2 = 0");
var result4 = rangeOfNumbers.AsQueryable().Select("it % 2 == 0 ? true : false");
}
public class TestData
{
public string Name { get; set; }
public int Age { get; set; }
public string Data1 { get; set; }
public string Data2 { get; set; }
public int intData1 { get; set; }
public int intData2 { get; set; }
}
}
}
C# RadzenButton ToolTip / Busy indicator 표시하기 (0) | 2024.03.30 |
---|---|
C# Balzor Page 에서 NavMenu 로 데이터 전달하기 (0) | 2024.03.23 |
C# DataSet ReadXML 오류 '경로에 잘못된 문자가 있습니다.' (0) | 2024.03.13 |
C# DataTable은 Xml에서 스키마 유추를 지원하지 않습니다. (0) | 2024.03.13 |
C# MemoryPack (0) | 2024.03.06 |