1

我对 LINQ 中的连接有疑问。我目前正在将访问应用程序转换为 .NET,其中数据是从两个不同服务器上的两个不同数据库中检索的。在旧应用程序中,可以通过一个查询来检索数据:

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

我发现在 .NET 中执行此操作的一种方法是分别检索两个表,然后使用 LINQ 将它们连接起来。我在 LINQ 方面没有经验,所以我的逻辑或代码可能完全错误,因为我似乎无法让它工作。

首先,我尝试进行普通连接(不对),但是当两个表包含近 2000 行时,只返回 18 行。我还检查了数据,它肯定会导致更多行,没有那么多空单元格。因此,我将右/左连接放在一起,但这实际上会导致错误。当我调试它时,执行 LINQ 语句时一切都很好,但是当我进入 foreach 时,会显示一个错误,并且错误实际上是在 linq 语句中指示的,说 table2 是空的。当我检查 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.

第二个查询:

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 回答