join を使用する場合、Linq の select 句で使用される匿名型を通過できないようです。クエリ結果をデータテーブルに入れたい。実行時にメモリにあるものは次のとおりです...
DataTable1 (source)
----------
col1A <int> (acting PK, not explicitly defined as such)
col1B <string>
col1C <string>
col1D <string> (FK -> dt2.col2A, also not explicitly defined)
col1E <string>
DataTable2 (source)
----------
col2A <string> (acting PK, also not explicitly defined)
col2B <string>
DataTable3 (destination)
----------
colA <int>
colB <string>
colC <string>
colD <string>
これが私が欲しいものです(私が探しているものと同等のSQL)...
INSERT INTO DataTable3 (colA, colB, colC, colD)
SELECT dt1.col1A, dt1.col1B, dt1.col1C, dt2.col2B
FROM DataTable1 dt1
LEFT JOIN DataTable2 dt2 ON (dt1.col1D = dt2.col2A)
逆に作業すると、列挙されたクエリ結果セットをデータテーブルに配置する次の単純な行が表示されます。
DataTable DataTable3 = query.CopyToDataTable();
これが私が試したことです...これを使用できるようにする方法で「クエリ」を作成する方法がわかりません。試行 1 (var クエリを使用。これはうまくいきました。詳細をお読みください):
var query =
from dt1 in DataTable1.AsEnumerable()
join dt2 in DataTable2.AsEnumerable()
on dt1.Field<string>("col1D") equals dt2.Field<string>("col2A")
select new { col1A = dt1.Field<int>("col1A"),
col1B = dt1.Field<string>("col1B"),
col1C = dt1.Field<string>("col1C"),
col2B = dt2.Field<string>("col2B") };
しかし、「query.CopyToDataTable()」で次のエラーが表示されます。
「エラー 1 型 'AnonymousType#1' は、ジェネリック型またはメソッド 'System.Data.DataTableExtensions.CopyToDataTable(System.Collections.Generic.IEnumerable)' で型パラメーター 'T' として使用できません。暗黙的な参照変換はありません。 'AnonymousType#1' から 'System.Data.DataRow' へ。"
私が推測できることから、このエラーは、「select new」が DataRows を「query」に構築しないためです。これは .CopyToDataTable() が要求します。匿名のレコードを作成するだけです。さらに、「保護レベルのためにアクセスできない」ため、クエリ要素を DataRow にキャストする方法がわかりません。
試行 2 (IEnumerable クエリを使用します。気にしないでください):
IEnumerable<DataRow> query =
from dt1 in DataTable1.AsEnumerable()
join dt2 in DataTable2.AsEnumerable()
on dt1.Field<string>("col1D") equals dt2.Field<string>("col2A")
select new { col1A = dt1.Field<int>("col1A"),
col1B = dt1.Field<string>("col1B"),
col1C = dt1.Field<string>("col1C"),
col2B = dt2.Field<string>("col2B") };
これにより、「結合」でエラーが発生します。
「エラー 5 型 'System.Collections.Generic.IEnumerable' を 'System.Collections.Generic.IEnumerable' に暗黙的に変換できません。明示的な変換が存在します (キャストがありませんか?)」
ちなみに、「join」句 (および「select」内の対応する dt2 列) をコメントアウトすると、「select」で次のエラーが発生します。
「エラー 2 型 'System.Data.EnumerableRowCollection' を 'System.Collections.Generic.IEnumerable' に暗黙的に変換できません。明示的な変換が存在します (キャストがありませんか?)」
また、列を使用して DataTable3 を事前定義して、「select」句に実際の DataRow を適用しようとしましたが、「select」を利用してそれを利用することはできませんでした。
編集、詳細、解決策: 助けてくれたティムに感謝します。試行 1 (var クエリ) を使用しました。また、DataTable3 を次のように事前定義しました。
DataTable DataTable3 = new DataTable();
DataTable3.Columns.Add("colA", System.Type.GetType("System.Int32"));
DataTable3.Columns.Add("colB", System.Type.GetType("System.String"));
DataTable3.Columns.Add("colC", System.Type.GetType("System.String"));
DataTable3.Columns.Add("colD", System.Type.GetType("System.String"));
ティムが提案したように、foreach ループを使用して「クエリ」の結果を保存しました。
foreach (var x in query)
{
DataRow newRow = DataTable3.NewRow();
newRow.SetField("colA", x.col1A);
newRow.SetField("colB", x.col1B);
newRow.SetField("colC", x.col1C);
newRow.SetField("colD", x.col2B);
DataTable3.Rows.Add(newRow);
}
これは、いくつかの追加の努力によっていくつかの方法で一般化できますが、私の目的にはこれで十分でした。