c#-4.0 - 来自第二个 DataTable.Merge 的数据不可用
问题描述
我正在使用 SQL Server 2012 Express 开发 C# 4.0 WinForms 应用程序。
我需要将 2 个表中的数据合并到一个 DataTable 中。在创建数据集、将 2 个查询传递给 SqlDataAdapter 然后填充数据集时,我尝试使用下面的 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 中可能是不切实际的。因此,我在没有解决方案的情况下结束了这个问题。我很感激我收到的回复。
解决方案
据我所知,这就是可能发生的事情。未知“什么”字段在“合并”表DataTables
dt1
中dt2.
时,“匹配”的列名将“合并”到一 (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();
}
}
我希望这是有道理的。
推荐阅读
- c++ - C++ 如何防止内存保护违规?
- python-3.x - 如何正确使用 image_dataset_from_directory?
- java - Hibernate - 在保存时将生成的 id 插入除 id 1 之外的列中
- laravel - LARAVEL 8 - 会话过期后在锁定页面中重定向
- wpf - 如何使用xaml画一条带箭头和直角的线
- django - Django 更改模型、迁移和更新现有记录
- java - 使用带有 localDateTime 的 Spring Boot 时出现 400 错误请求
- python - Python Telethon:抓取和存储 Telegram 消息
- ruby-on-rails - Activeadmin年选择只有10年之前
- excel - 我在 VBA 的 for 循环中遇到类型不匹配错误