1

LINQ の結合について質問があります。私は現在、2 つの異なるサーバー上の 2 つの異なるデータベースからデータを取得するアクセス アプリケーションを .NET に変換しています。古いアプリケーションでは、データは 1 つのクエリで取得できました。

SELECT *, tbl2.Descr, tbl2.Form FROM tbl2 RIGHT JOIN tbl1 on tbl2.proId2 = tbl1.proId

.NET でこれを行う 1 つの方法は、2 つのテーブルを別々に取得してから、それらを LINQ で結合することです。私は LINQ の経験がないので、ロジックやコードが完全に間違っている可能性があります。

最初に通常の結合を試みましたが (正しくありません)、2 つのテーブルにほぼ 2000 行が含まれている場合、18 行しか返されません。私もデータをチェックしましたが、間違いなくより多くの行が得られるはずです。空のセルはそれほど多くありません。それで、右/左の結合をまとめましたが、これは実際にはエラーになります。デバッグすると、LINQ ステートメントが実行されるとすべて問題ありませんが、foreach に入ると、エラーが表示され、テーブル 2 が空であるというエラーが実際に linq ステートメントに示されます。table1 を確認すると、22 個のデータ行しか表示されません。

私は何を間違っていますか?

DataTable dtTarget= data1.Clone();
var dt2Columns = data2.Columns.OfType<DataColumn>().Select(dc =>
     new DataColumn(dc.ColumnName, dc.DataType, dc.Expression, dc.ColumnMapping));
var dt2FinalColumns = from dc in dt2Columns.AsEnumerable()
                    where dtTarget.Columns.Contains(dc.ColumnName) == false
                              select dc;

dtTarget.Columns.AddRange(dt2FinalColumns.ToArray());

var results = from table1 in data1.AsEnumerable()
              join table2 in data2.AsEnumerable() 
              on table1.Field<String>("proId") equals table2.Field<String>("proId2")
              select table1.ItemArray.Concat(table2.ItemArray).ToArray();

foreach (object[] values in results)
            dtTarget.Rows.Add(values);

外部結合:

var results = from table1 in data1.AsEnumerable()
              join table2 in data2.AsEnumerable() on table1.Field<String>("proId")     equals table2.Field<String>("proId2") into t_join
              from table2 in t_join.DefaultIfEmpty(null) select table1.ItemArray.Concat(table2.ItemArray).ToArray();
4

1 に答える 1

0

結合キーとして文字列を使用していることに気付きました。おそらく、文字列の比較は環境間 (アクセスと .net) で異なります。Access では大文字と小文字を区別しない比較が使用される場合がありますが、.net のデフォルトでは大文字と小文字が区別されます。

.net で大文字と小文字を区別しない比較を使用するには、最初のクエリを次に示します。

var results = data1.AsEnumerable()
  .Join(
    data2.AsEnumerable(),
    row1 => row1.Field<String>("proId"),
    row2 => row2.Field<String>("proId2"),
    (row1, row2) => row1.ItemArray.Concat(row2.ItemArray).ToArray(),
    StringComparer.InvariantCultureIgnoreCase); //and now caps are ignored.

そして2番目のクエリ:

var results = data1.AsEnumerable()
  .GroupJoin(
    data2.AsEnumerable(),
    row1 => row1.Field<String>("proId"),
    row2 => row2.Field<String>("proId2"),
    (row1, row2s) => new {Row1 = row1, Row2s = row2s},
    StringComparer.InvariantCultureIgnoreCase)
  .SelectMany(
    x => x.row2s.DefaultIfEmpty(null)),
    (x, row2) => row2 == null ? x.Row1.ItemArray : x.Row1.ItemArray.Concat(row2.ItemArray).ToArray()
  );
于 2013-02-14T14:07:31.273 に答える