.NET DataTable跳过Load(DataReader)上的行
-
04-07-2019 - |
题
我正在尝试使用以下内容填充DataTable以构建LocalReport:
MySqlCommand cmd = new MySqlCommand();
cmd.Connection = new MySqlConnection(Properties.Settings.Default.dbConnectionString);
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT ... LEFT JOIN ... WHERE ..."; /* query snipped */
// prepare data
dataTable.Clear();
cn.Open();
// fill datatable
dt.Load(cmd.ExecuteReader());
// fill report
rds = new ReportDataSource("InvoicesDataSet_InvoiceTable",dt);
reportViewerLocal.LocalReport.DataSources.Clear();
reportViewerLocal.LocalReport.DataSources.Add(rds);
有一次,我注意到报告不完整,缺少一条记录。我已经更改了一些条件,以便查询将返回两行并且... 意外:报告只显示一行而不是两行。我试图调试它以找出问题所在,我陷入了
dt.Load(cmd.ExecuteReader());
当我注意到 DataReader
包含两条记录但 DataTable
只包含一条记录时。不小心,我在查询中添加了 ORDER BY
子句,并注意到这次报告正确显示。
显然,DataReader包含两行,但如果SQL查询字符串包含 ORDER BY
,则DataTable只读取它们(否则它只读取最后一行)。任何人都可以解释为什么会发生这种情况以及如何解决这个问题?
修改:
当我第一次发布问题时,我说它正在跳过第一行;后来我意识到它实际上只读了最后一行并且我相应地编辑了文本(当时所有的记录都被分成两行,当它实际上只显示最后一行时它似乎跳过了第一行)。这可能是因为它没有唯一的标识符来区分MySQL返回的行,因此添加 ORDER BY
语句会导致它为每行创建唯一标识符。点击
这只是一个理论,我没有任何支持它,但我所有的测试似乎都会产生相同的结果。
解决方案
我有同样的问题。我从您的博客中提取了提示,并在查询中放置了ORDER BY子句,以便它们可以一起形成查询返回的所有记录的唯一键。它解决了这个问题。有点奇怪。
其他提示
在摆弄了很多东西之后,我发现DataTable.Load方法需要底层数据中的主键列。如果您仔细阅读文档,这很明显,尽管没有明确说明。
如果您有一个名为“id”的列它似乎使用它(为我修复它)。否则,它似乎只是使用第一列,无论它是否唯一,并在读取时覆盖该列中具有相同值的行。如果您没有名为“id”的列并且您的第一列不是唯一的,我建议在加载datareader之前尝试显式设置数据表的主键列。
以防任何人遇到类似癌症的问题,我使用If DataReader.Read
...而不是If DataReader.HasRows
来检查存在之前是否存在 dt.load(DataReader)
Doh!
有同样的问题。这是因为所有行上的主键都是相同的。它可能是用来键入结果的东西,因此它只是一遍又一遍地覆盖同一行。
Datatables.Load指向fill方法以了解其工作原理。此页面表明它是主键识别。由于主键只能出现一次并用作行的键...
" Fill操作然后将行添加到DataSet中的目标DataTable对象,如果它们尚不存在则创建DataTable对象。创建DataTable对象时,“填充”操作通常仅创建列名元数据。但是,如果将MissingSchemaAction属性设置为AddWithKey,则还会创建相应的主键和约束。 (http://msdn.microsoft.com/en-us/library/zxkb3c3d.aspx)
今天遇到了这个问题。
不幸的是,这个线程中没有任何内容修复它,但后来我将SQL查询包装在另一个SELECT语句中并且它可以工作了!
例如:
SELECT * FROM (
SELECT ..... < YOUR NORMAL SQL STATEMENT HERE />
) allrecords
...奇怪
不要使用
dr.Read()
因为它将指针移动到下一行。 删除此行希望它能够正常工作。
您是否可以获取从SQL事件探查器运行的实际查询并尝试运行它?它可能不是你所期望的。
使用SqlDataAdapter.Fill(dataTable)时是否得到相同的结果?
你在读者上尝试过不同的命令行为吗? MSDN文档
我知道这是一个老问题,但对我而言,在查询访问数据库并注意到它缺少查询的一行时有效的想法是更改以下内容: -
if(dataset.read()) - Misses a row.
if(dataset.hasrows) - Missing row appears.
不确定为什么你错过了数据表中的行,是否可能需要关闭阅读器?在任何情况下,这是我通常加载报告的方式,每次都有效...
Dim deals As New DealsProvider()
Dim adapter As New ReportingDataTableAdapters.ReportDealsAdapter
Dim report As ReportingData.ReportDealsDataTable = deals.GetActiveDealsReport()
rptReports.LocalReport.DataSources.Add(New ReportDataSource("ActiveDeals_Data", report))
很想知道它是否仍然存在。
在我的情况下,ORDER BY和dt.AcceptChanges()都不起作用。我不知道为什么会出现这个问题。我在数据库中有50条记录,但它只在数据表中显示49条记录。跳过第一行,如果datareader中只有一条记录,则它根本不显示任何内容。
什么是bizzareeee .....
您是否尝试在 dt.Load(cmd.ExecuteReader())
之后调用 dt.AcceptChanges()
以查看是否有帮助?
我知道这是一个老问题,但我遇到了同样的问题,这里提到的解决方法都没有帮助。
就我而言,在用作 PrimaryKey
的列上使用别名解决了这个问题。
所以,而不是
SELECT a
, b
FROM table
我用过
SELECT a as gurgleurp
, b
FROM table
并且有效。
我有同样的问题..根本不使用dataReader.Read()..它将指针指向下一行。而是直接使用datatable.load(dataReader)。