首页 > 解决方案 > 来自第二个 DataTable.Merge 的数据不可用

问题描述

我正在使用 SQL Server 2012 Express 开发 C# 4.0 WinForms 应用程序。

我需要将 2 个表中的数据合并到一个 DataTable 中。在创建数据集、将 2 个查询传递给 SqlDataAdapter 然后填充数据集时,我尝试使用下面的 2 条建议。

如何用多个表填充数据集?

合并 2 个数据表并存储在一个新的数据表中

我创建了 2-DataTables,即 dt1 和 dt2,将第一个表“Table”分配给 DataTable dt1。我已将第二个表“Table1”分配给下一个 DataTable,即 dt2。我创建了第三个 DataTable dtAll 并尝试合并表,如下所示。

//Other variables not shown
string dateIN = "";
string dateOUT = "";
DataSet ds = new DataSet();
//SqlConnection here
conn.Open();

SqlDataAdapter adap = new SqlDataAdapter(
"SELECT * FROM AssignmentsIN WHERE ScheduledDateIN BETWEEN @start AND @end ORDER BY ScheduledDateIN ASC; SELECT * FROM AssignmentsOUT WHERE ScheduledDateOUT BETWEEN @start AND @end ORDER BY ScheduledDateOUT ASC", conn);

adap.SelectCommand.Parameters.Add("@start", SqlDbType.NVarChar).Value = dStart;
adap.SelectCommand.Parameters.Add("@end", SqlDbType.NVarChar).Value = dEnd;

adap.TableMappings.Add("Table", "AssignmentsIN");
adap.TableMappings.Add("Table1", "AssignmentsOUT");
adap.Fill(ds);

DataTable dt1 = ds.Tables["AssignmentsIN"];
DataTable dt2 = ds.Tables["AssignmentsOUT"];
DataTable dtAll;
dtAll = dt1.Copy();
dtAll.Merge(dt2);
                
foreach (DataRow row in dtAll.Rows)
{
    dateIN = row.Field<string>("ScheduledDateIN").Trim();//The data here shows up!
    //Data from 1st table shows up correctly. 

    dateOUT = row.Field<string>("ScheduledDateOUT").Trim();
    //^^ This begins the line where it throws the exception ^^
    //However, when the code attempts to access data from the 2nd table it errors.
}

我遇到的问题是,当我的代码到达我试图访问驻留在 dt2 中的数据的地方时,它会抛出异常“对象引用未设置为对象的实例”。

DateIN 和 DateOUT 都是字符串类型的字段,而不是 DateTime。如下所述,如果我查看 DataSet,我实际上可以“查看”第二个表中的数据。它显示在 row.ItemArray 中。我的问题仍然是,如何成功地将这些 2 表合并到一个 DataTable 中。dtAll 具有来自第一个表的数据。如何将数据从 dt2 获取到 dtAll?

如果我深入到 DataSet ds,我可以看到第二个表中的数据。如何填充两个数据表,即 dt1 和 dt2 并将它们合并到 dtAll 并成功访问第二个表中的数据?

更新:在进一步研究数据表合并后;因为 2-database 表具有不同的数据结构,所以我意识到尝试将它们合并到一个 DataTable 中可能是不切实际的。因此,我在没有解决方案的情况下结束了这个问题。我很感激我收到的回复。

标签: c#-4.0datatable

解决方案


据我所知,这就是可能发生的事情。未知“什么”字段在“合并”表DataTables dt1dt2.时,“匹配”的列名将“合并”到一 (1) 列中。例子; 如果两个表都有一个string名为“Col0”的类型列并执行……</p>

dtAll = dt1.Copy();
dtAll.Merge(dt2);

然后,在合并dtAll表中,将有一个名为“Col0”的列,它将包含来自“BOTH”表中名为“Col0”的列的值。dtAll由于列名相同,因此两个表的值都将合并到表中的一 (1) 列中。

但是,如果合并表包含第一个表中不包含的列名,那么它将在合并表中创建一个具有第二个表唯一列名的“新”列,并且它将将该列的数据以“AFTER”开头” 第一个表的行。

例子; 查看发布的代码,似乎有一个dt1名为“ScheduledDateIN”的列。此外,在表dt2中似乎有一列名为“ScheduledDateOUT”。如果这些表被合并,你最终会得到类似......</p>

在此处输入图像描述

从列中可以看出,ScheduledDateOut第一个表行中该字段的所有值都是null.。从图片中还可以注意到,名称为“SAME”的列合并为一列。因此,我假设上面的图片将代表您在执行上述命令后得到的结果。

目前尚不清楚这是否是您想要的,但是,这肯定会解释null您遇到的异常。异常的原因是......

如果我们看一下foreach循环……</p>

foreach (DataRow row in dtAll.Rows)
{
  dateIN = row.Field<string>("ScheduledDateIN").Trim();
  dateOUT = row.Field<string>("ScheduledDateOUT").Trim();
}

这将遍历合并dtAll表中的所有行。所以,使用上面的图片,在第一行…</p>

dateIN = row.Field<string>("ScheduledDateIN").Trim();

这没有问题,因为在第一行的“ScheduledDateIN”字段中有一个“值”。但是,在下一行……</p>

dateOUT = row.Field<string>("ScheduledDateOUT").Trim();

此行将引发您注意到的异常,因为从图片中可以看出,第一行上“ScheduledDateOUT”字段的值是empty/null.因此,当您尝试.Trim()对一个值调用 strings 方法时,null您将获得null你已经知道的例外。

如果您可以继续循环,当循环到达第 11 行(从图片中)时,第一行将引发相同的异常,因为“ScheduledDateIN”字段的值是empty/null.

由于在“合并”表时并不完全清楚您想要实现的目标,因此我可以提供的唯一解决方案是null“在”尝试调用该Trim()方法之前“检查”这些值。此解决方案可能如下所示。

foreach (DataRow row in dtAll.Rows) {
  if (row.Field<string>("ScheduledDateIN") != null) {
    var dateIN = row.Field<string>("ScheduledDateIN").Trim();//The data here shows up!
  }
  if (row.Field<string>("ScheduledDateOUT") != null) {
    var dateOUT = row.Field<string>("ScheduledDateOUT").Trim();
  }
}

我希望这是有道理的。


推荐阅读