.NET DataTable跳过Load(DataReader)上的行

时间:2008-10-23 11:41:40

标签: .net datatable datareader localreport

我正在尝试使用以下内容填充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语句会导致它为每行创建唯一标识符。
这只是一个理论,我没有任何支持它,但我所有的测试似乎都会产生相同的结果。

14 个答案:

答案 0 :(得分:7)

问题已经有好几年了,但除了上面提到的解决方法外,我还没有找到合适的答案。

在摆弄了很多东西之后,我发现DataTable.Load方法需要底层数据中的主键列。如果您仔细阅读文档,这很明显,尽管没有明确说明。

如果你有一个名为“id”的列,它似乎使用它(为我修复它)。否则,它似乎只是使用第一列,无论它是否唯一,并在读取时覆盖该列中具有相同值的行。如果您没有名为“id”的列并且您的第一列不是唯一的,我建议在加载datareader之前尝试显式设置数据表的主键列。

答案 1 :(得分:5)

如果有人遇到类似癌症的问题,我在调用DataReader.Read Doh之前使用If DataReader.HasRows而不是If dt.load(DataReader)来检查存在!

答案 2 :(得分:4)

有同样的问题。这是因为所有行上的主键都是相同的。它可能是用来键入结果的东西,因此它只是一遍又一遍地覆盖同一行。

Datatables.Load指向fill方法以了解其工作原理。此页面表明它是主键识别。由于主键只能出现一次并用作行的键...

“Fill操作然后将行添加到DataSet中的目标DataTable对象,创建DataTable对象(如果它们尚不存在)。创建DataTable对象时,Fill操作通常只创建列名元数据。但是,如果MissingSchemaAction property设置为AddWithKey,还会创建相应的主键和约束。“ (http://msdn.microsoft.com/en-us/library/zxkb3c3d.aspx)

答案 3 :(得分:4)

今天遇到了这个问题。

不幸的是,这个线程中没有任何内容修复它,但后来我将SQL查询包装在另一个SELECT语句中并且它可以工作了!

例如:

SELECT * FROM (
    SELECT ..... < YOUR NORMAL SQL STATEMENT HERE />
) allrecords

...奇怪

答案 4 :(得分:3)

不要使用

dr.Read()

因为它将指针移动到下一行。 删除此行希望它能够正常工作。

答案 5 :(得分:2)

我有同样的问题。我从您的博客中提取了提示,并在查询中放置了ORDER BY子句,以便它们可以一起形成查询返回的所有记录的唯一键。它解决了这个问题。有点奇怪。

答案 6 :(得分:1)

您是否可以获取从SQL事件探查器运行的实际查询并尝试运行它?它可能不是你所期望的。

使用SqlDataAdapter.Fill(dataTable)时是否得到相同的结果?

你在读者上尝试过不同的命令行为吗? MSDN Docs

答案 7 :(得分:1)

我知道这是一个老问题,但对我而言,在查询访问数据库并注意到它缺少查询的一行时有效的想法是更改以下内容: -

    if(dataset.read())  - Misses a row.

    if(dataset.hasrows) - Missing row appears.

答案 8 :(得分:1)

对于像我这样遇到此线程的其他任何人,有关由MySql的唯一ID填充DataTable的答案都是正确的。

但是,如果一个表包含多个唯一ID,但MySql命令仅返回一个ID(而不是使用'*'来接收所有列),则该DataTable将仅根据给定并执行的单个ID进行组织就像您的查询中使用了“ GROUP BY”一样。

因此,简而言之,DataReader将提取所有记录,而DataTable.Load()将仅看到检索到的唯一ID,并使用该ID填充DataTable,从而跳过信息行

答案 9 :(得分:0)

不确定为什么你错过了数据表中的行,是否可能需要关闭阅读器?在任何情况下,这是我通常加载报告的方式,每次都有效...

        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))

很想知道它是否仍然存在。

答案 10 :(得分:0)

您是否尝试在dt.AcceptChanges()来电后致电dt.Load(cmd.ExecuteReader()),看看是否有帮助?

答案 11 :(得分:0)

在我的情况下,ORDER BY和dt.AcceptChanges()都不起作用。我不知道为什么会出现这个问题。我在数据库中有50条记录,但它只在数据表中显示49条记录。跳过第一行,如果datareader中只有一条记录,则它根本不显示任何内容。

什么是bizzareeee .....

答案 12 :(得分:0)

我知道这是一个老问题,但我遇到了同样的问题,这里提到的解决方法都没有帮助。

就我而言,在用作PrimaryKey的列上使用别名解决了这个问题。

所以,而不是

SELECT a
     , b
FROM table

我用过

SELECT a as gurgleurp
     , b
FROM table

并且有效。

答案 13 :(得分:0)

我有同样的问题..根本不使用dataReader.Read()..它将指针指向下一行。而是直接使用datatable.load(dataReader)。