DataTable.Load(FbDataReader)不能将所有内容加载到DataTable中。

11

这里有一个相关的问题:.NET DataTable skips rows on Load(DataReader)

我有一个SQL查询,返回了169个结果。结果看起来像这样:

CustomerID Customer Name TerminalID Creation Date
     1     First Customer   12345   2010-07-07
     1     First Customer   12346   2010-07-07
     1     First Customer   12347   2010-07-07
     2     Second Customer  23456   2011-04-18

这个结果是正确的。

我在一个C#程序中输入了查询,并像这样执行它:

public DataTable getDataTableFromSql(FbCommand command)
{
    // Create a new datatable
    DataTable result = new DataTable();

    // Set up the connection
    using (FbConnection con = new FbConnection(this.connectionString))
    {
        // Open the connection
        con.Open();

        // Set up the select command
        FbCommand sqlCmd = command;
        // Add the connection to it
        sqlCmd.Connection = con;

        try
        {
            // Get the results
            using (FbDataReader sqlReader = sqlCmd.ExecuteReader())
            {
                // Load the results into the table
                result.Load(sqlReader);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }
    }

    // Return the table
    return result;
}

这段代码经过测试,在许多不同的SQL查询中都能正常工作。 但对于上述查询,DataTable仅包含39个结果,且如下所示:

CustomerID Customer Name TerminalID Creation Date
     1     First Customer   12347   2010-07-07
     2     Second Customer  23456   2011-04-18

我稍微调整了一下代码,目前的发现是: FbDataReader 正确地从数据库中获取了结果。如果我只查询 TerminalID,那么在 DataTable 中会得到 169 个结果。如果我查询 CustomerID,那么我将收到 39 个结果。

结论:result.Load(sqlReader) 对于 CustomerID 进行了分组,并且放弃了所有其他结果,无论它们是否可以分组。

为什么会这样?我该如何将查询结果加载到 DataTable 中而不因不合逻辑的分组而“丢失”任何行?为什么 DataTable 会首先对结果进行“分组”?

注意:我还尝试了 DataTables 可用的所有三个 LoadOptions,但结果相同:只有 39 个结果被加载到 DataTable 中。


你尝试过使用数据适配器填充吗? - kostas ch.
如果我只查询终端ID是什么意思?如果你要检查DataTable内容,你要在哪里以怎样的方式来查询它? - Tim Schmelter
@TimSchmelter:这意味着我编辑我的SQL查询,以便仅返回“TerminalId”列。当我再次运行程序时,我会在“DataTable”中收到所有169个结果。 - waka
@waka:DataReader返回多少条记录?您是否在循环中使用了一个int变量(while(sqlReader.Read()count++;))来查看数据库是否返回了39或169条记录?这样,您至少会知道您的问题是否与DataTable.Load或查询有关。 - Tim Schmelter
@TimSchmelter:是的,我已经检查过了。FbDataReader工作正常,并返回所有应返回的结果。问题确实与DataTable.Load()有关。 - waka
1
可能是.NET DataTable skips rows on Load(DataReader)的重复问题。 - Mark Rotteveel
3个回答

6
DataTable.Load方法要求底层数据(即来自DataReader)中有一个主键列。看起来你的过程没有任何主键列,或者如果你有一个,请在sql语句中使用order by,以便DataTable能够将其作为主键接受。
这是一个非常老的问题,关于DataTable.Load并没有很好的文档记录。一般情况下,SQLDataAdapterDataTable兼容性很好。
在你的情况下,我认为只要Load发现重复项就会停止加载数据。我没有在任何地方找到这个记录,但看起来这是问题所在。

5

即使我不知道问题所在,我建议使用DataAdapter。也许这会起作用:

// Get the results
using(var da = new FbDataAdapter(sqlCmd))
{
    // Load the results into the table
    da.Fill(result);
}

为什么会发生这种情况?我认为这个答案在另一个问题中已经解释了。


1
我刚刚测试了一下,DataTable 中返回了 169 条结果,谢谢!但我真的很想知道为什么 DataTable.Load() 似乎“吞噬”了一些结果... :/ - waka
1
@waka:这里有一个类似的问题:https://dev59.com/2HVC5IYBdhLWcg3woStW - Tim Schmelter
1
谢谢,我现在知道发生了什么。我会编辑我的问题并包含我的想法。 - waka

3
解决问题的方案如下: DataTable.Load()在结果中查找一个主键。如果尝试将其加载到DataTable中的主键已经存在于该表中,则用新结果覆盖该行。
然而,为具有主键的列使用不同的别名可以解决问题,这样所有结果都将被加载到DataTable中,因为似乎使用别名覆盖了该列是一个主键的信息。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接