実現したいこと
2つのDataTableを受け、LINQを用いて特定のキーで外部結合し、SQLのSELECT *
に相当する結果をDataTableで返す関数を実装したいです。
DataTableは任意のCSVを読み込んで作成するので、LINQメソッド内でSELECTするカラム名を指定できないため、このような質問をさせて頂きました。
現状
下記質問を参考に内部結合は実装できたのですが、
https://teratail.com/questions/131794
外部結合するためのGroupJoin
の使うまでは分かったのですが、正解の実装方法がわからない状態です。
C#
1public class Program 2{ 3 static void Main(string[] args) 4 { 5 // 結合されるデータテーブル 6 DataTable dtX = new DataTable(); 7 dtX.Columns.Add("key", typeof(string)); 8 dtX.Columns.Add("valX", typeof(double)); 9 dtX.Rows.Add("AAA", 1); 10 dtX.Rows.Add("BBB", 2); 11 dtX.Rows.Add("CCC", 3); 12 13 // 結合するデータテーブル 14 DataTable dtY = new DataTable(); 15 dtY.Columns.Add("key", typeof(string)); 16 dtY.Columns.Add("valY", typeof(int)); 17 dtY.Columns.Add("valYY", typeof(int)); 18 dtY.Rows.Add("AAA", 10, 11); 19 dtY.Rows.Add("BBB", 20, 22); 20 21 // 結合実行 22 GetJoinedDataTable(dtX, dtY); 23 } 24 25 // 結合メソッド 26 public static DataTable GetJoinedDataTable(DataTable dtFrom, DataTable dtJoin) 27 { 28 DataTable dtResult = new DataTable(); 29 foreach (DataColumn column in dtFrom.Columns) 30 { 31 dtResult.Columns.Add("from." + column.ColumnName, typeof(string)); 32 } 33 foreach (DataColumn column in dtJoin.Columns) 34 { 35 dtResult.Columns.Add("join." + column.ColumnName, typeof(string)); 36 } 37 38 var methodQ = dtFrom.AsEnumerable().Join( 39 dtJoin.AsEnumerable(), 40 f => f["key"], 41 j => j["key"], 42 (f, j) => 43 { 44 DataRow row = dtResult.NewRow(); 45 row.ItemArray = f.ItemArray.Concat(j.ItemArray).ToArray(); 46 dtResult.Rows.Add(row); 47 return row; 48 }); 49 50 return methodQ.CopyToDataTable(); 51 } 52}
一応m外部結合用メソッド実装tryしてみたのですが、
結合するデータテーブルに1つでもキーが不足している場合(結合結果カラムの値がNULLになる場合)正しいデータテーブルで結果が帰ってきません。
DataTable dtResult = new DataTable(); foreach (DataColumn column in dtFrom.Columns) { dtResult.Columns.Add("from." + column.ColumnName, typeof(string)); } foreach (DataColumn column in dtJoin.Columns) { dtResult.Columns.Add("join." + column.ColumnName, typeof(string)); } var methodQ = dtFrom.AsEnumerable().GroupJoin( dtJoin.AsEnumerable(), f => f["key"], j => j["key"], (f, tmpj) => new { f = f, tmpj = tmpj }) .SelectMany ( x => x.tmpj.DefaultIfEmpty(), (x, j) => { DataRow row = dtResult.NewRow(); row.ItemArray = x.f.ItemArray.Concat(j.ItemArray).ToArray(); dtResult.Rows.Add(row); return row; } );
実装できる方おられましたら、どうかお力添えお願い致します。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。