Linq는 결국 메서드 호출!
다음과 같은 질문이 있군요. ^^
2개의 DataTable Join 결과 전체 컬럼을 DataTable 로 리턴하기
; https://www.sysnet.pe.kr/3/0/3701
정리해 보면, 다음과 같은 식으로 DataTable이 마련되어 있을 때,
DataTable dtResult = new DataTable();
dtResult.Columns.Add("ID", typeof(string));
dtResult.Columns.Add("name", typeof(string));
dtResult.Columns.Add("stock", typeof(int));
dtResult.Columns.Add("ID2", typeof(string));
dtResult.Columns.Add("name2", typeof(string));
dtResult.Columns.Add("stock2", typeof(int));
DataTable table1 = new DataTable();
table1.Columns.Add("ID", typeof(string));
table1.Columns.Add("name", typeof(string));
table1.Columns.Add("stock", typeof(int));
table1.LoadDataRow(new object[] { "5", "test1", 500 }, true);
table1.LoadDataRow(new object[] { "6", "test2", 600 }, true);
table1.LoadDataRow(new object[] { "7", "test3", 700 }, true);
DataTable table2 = new DataTable();
table2.Columns.Add("ID2", typeof(string));
table2.Columns.Add("name2", typeof(string));
table2.Columns.Add("stock2", typeof(int));
table2.LoadDataRow(new object[] { "5", "test12", 510 }, true);
table2.LoadDataRow(new object[] { "6", "test22", 610 }, true);
table2.LoadDataRow(new object[] { "7", "test32", 710 }, true);
한번의 LINQ 쿼리로 tabl1과 table2의 join 결과를 dtResult에 담고 싶다는 것입니다. 물론, 질문하신 분의 2가지 Linq 쿼리는 그런 것을 못한다는 것이고, 제가 답변을 한 StackOverflow의 글에서는 그에 대한 해결책이 표현되어 있습니다.
간단합니다. 다음과 같이 해주면 해결됩니다.
var result = from dataRows1 in table1.AsEnumerable()
join dataRows2 in table2.AsEnumerable()
on dataRows1.Field<string>("ID") equals dataRows2.Field<string>("ID2")
select dtResult.LoadDataRow(dataRows1.ItemArray.Concat(dataRows2.ItemArray).ToArray<object>(), false);
DataTable my = result.CopyToDataTable();
실제로 위의 코드를 실행해서 출력해 보면,
DataSet ds = new DataSet("test");
ds.Tables.Add(my);
Console.WriteLine(ds.GetXml());
다음과 같은 결과를 얻습니다.
<test>
<Table1>
<ID>5</ID>
<name>test1</name>
<stock>500</stock>
<ID2>5</ID2>
<name2>test12</name2>
<stock2>510</stock2>
</Table1>
<Table1>
<ID>6</ID>
<name>test2</name>
<stock>600</stock>
<ID2>6</ID2>
<name2>test22</name2>
<stock2>610</stock2>
</Table1>
<Table1>
<ID>7</ID>
<name>test3</name>
<stock>700</stock>
<ID2>7</ID2>
<name2>test32</name2>
<stock2>710</stock2>
</Table1>
</test>
그런데, 여기서 제가 하고 싶은 말은... Linq는 단순한 메서드 호출의 나열에 불과하다는 것입니다. 일례로, 위의 Linq 쿼리에서 select 문을 개선해 볼까요?
var result = from dataRows1 in table1.AsEnumerable()
join dataRows2 in table2.AsEnumerable()
on dataRows1.Field<string>("ID") equals dataRows2.Field<string>("ID2")
select dtResult.LoadDataRow(dataRows1.ItemArray.Concat(dataRows2.ItemArray).ToArray<object>(), false);
가령, 다음과 같이 메서드로 바꿔줄 수 있습니다.
var result = from dataRows1 in table1.AsEnumerable()
join dataRows2 in table2.AsEnumerable()
on dataRows1.Field<string>("ID") equals dataRows2.Field<string>("ID2")
select MergeRows(dtResult, dataRows1, dataRows2);
private static DataRow MergeRows(DataTable table, DataRow dataRows1, DataRow dataRows2)
{
List<object> list = new List<object>();
list.AddRange(dataRows1.ItemArray);
list.AddRange(dataRows2.ItemArray);
return table.LoadDataRow(list.ToArray(), false);
}
또는, table 정의를 바꾸고 그에 맞게 데이터를 채우는 것도 가능합니다. 가령, 다음은 ID2 컬럼을 제외하고 있습니다.
DataTable dtResult = new DataTable();
dtResult.Columns.Add("ID", typeof(string));
dtResult.Columns.Add("name", typeof(string));
dtResult.Columns.Add("stock", typeof(int));
dtResult.Columns.Add("name2", typeof(string));
dtResult.Columns.Add("stock2", typeof(int));
var result = from dataRows1 in table1.AsEnumerable()
join dataRows2 in table2.AsEnumerable()
on dataRows1.Field<string>("ID") equals dataRows2.Field<string>("ID2")
select MergeRows2(dtResult, dataRows1, dataRows2);
private static DataRow MergeRows2(DataTable table, DataRow dataRows1, DataRow dataRows2)
{
List<object> list = new List<object>();
list.AddRange(dataRows1.ItemArray);
list.AddRange(dataRows2.ItemArray.Skip(1));
return table.LoadDataRow(list.ToArray(), false);
}
/*
<test>
<Table1>
<ID>5</ID>
<name>test1</name>
<stock>500</stock>
<name2>test12</name2>
<stock2>510</stock2>
</Table1>
<Table1>
<ID>6</ID>
<name>test2</name>
<stock>600</stock>
<name2>test22</name2>
<stock2>610</stock2>
</Table1>
<Table1>
<ID>7</ID>
<name>test3</name>
<stock>700</stock>
<name2>test32</name2>
<stock2>710</stock2>
</Table1>
</test>
*/
이 정도면... 대충 감이 오시죠? ^^
(
첨부 파일은 위의 예제 코드를 포함합니다.)
[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]