DataReader 中的倍数表

Posted

技术标签:

【中文标题】DataReader 中的倍数表【英文标题】:Multiples Table in DataReader 【发布时间】:2012-10-09 18:38:50 【问题描述】:

我通常使用DataSet,因为它非常灵活。最近我被分配了代码优化任务,为了减少对数据库的命中,我在一个过程中更改了两个查询。一个查询返回count,另一个返回actual data。也就是说,My stored procedure 返回两个表。现在,我知道如何使用DataSets 读取这两个表,但我需要使用DataReader 读取这两个表。在搜索过程中,我找到了This。

我按照文章写了这样的代码:

dr = cmd.ExecuteReader();
while (dr.Read())




if (dr.NextResult()) // this line throws exception

   while (dr.Read())

但我在 dt.NextResult 遇到异常。例外是:

Invalid attempt to call NextResult when reader is closed.

我也搜索了上面的错误,但仍然无法解决问题。 任何帮助都感激不尽。我需要使用datareader 读取多个表,这可能吗?

【问题讨论】:

我不明白的是:"一个Query返回计数,另一个返回实际数据。也就是说,我的存储过程返回两个表" count(这是一个标量值)一个 是的,它是标量值,但存储过程是使用动态查询编写的。两个查询都非常大,查询都写为 varchar,然后最后使用 Exec 执行。如果我将 Count 查询称为实际数据查询的子查询,则查询变量的大小非常大,并且执行时出错。所以为了避免这种情况,我写了两个不同的查询,这就是 Count 也来自一个表(第二个表)的原因。我希望我说清楚了。 【参考方案1】:

试试这个,因为一旦任务结束,这将关闭连接、数据读取器和命令,这样就不会给数据读取器关闭异常

也请像这样检查if(reader.NextResult()) 以检查是否有下一个结果,

using (SqlConnection connection = new SqlConnection("connection string here"))

    using (SqlCommand command = new SqlCommand
           ("SELECT Column1 FROM Table1; SELECT Column2 FROM Table2", connection))
    
        connection.Open(); 
        using (SqlDataReader reader = command.ExecuteReader())
        
            while (reader.Read())
            
                MessageBox.Show(reader.GetString(0), "Table1.Column1");
            

            if(reader.NextResult())
            
               while (reader.Read())
              
                MessageBox.Show(reader.GetString(0), "Table2.Column2");
              
            
        
    

【讨论】:

@muhammadkashif-您的错误是因为您的连接已关闭或 datareader 已关闭,因此最好也像这样检查...。也像我一样检查 if 子句中的 nextresultset这也可以帮助你...... 谢谢,我在使用后缺少 ,因为只有第一个 while 被认为是 Using 语句的一部分。谢谢,将在五分钟内将您的答案标记为已接受。 @muhammadkashif 您能否更新您的问题以显示您如何使用不正确的using …; 构造?这将澄清问题...... @Pranay Rana 我返回 4 个表,那么如何使用您的解决方案从第 3 和第 4 个表数据中获取数据,您能帮帮我吗??【参考方案2】:

我试图重现这个问题(也是因为我之前没有在阅读器中使用过多个表)。但它按预期工作,因此我假设您省略了相关代码。

这是我的测试代码:

using (var con = new SqlConnection(Properties.Settings.Default.ConnectionString))

    using (var cmd = new SqlCommand("SELECT TOP 10 * FROM tabData; SELECT TOP 10 * FROM tabDataDetail;", con))
    
        int rowCount = 0;
        con.Open();
        using (IDataReader rdr = cmd.ExecuteReader())
        
            while (rdr.Read())
            
                String object1 = String.Format("Object 1 in Row 0: '1'", ++rowCount, rdr[0]);
            
            if (rdr.NextResult())
            
                rowCount = 0;
                while (rdr.Read())
                
                    String object1 = String.Format("Object 1 in Row 0: '1'", ++rowCount, rdr[0]);
                
            
        
    

【讨论】:

谢谢,我的问题解决了,为你的努力投票。 如果我想使用 DataTable.Load() 而不是循环阅读器,那么第二个表就会被填充。这有什么线索吗? 终于找到了线索。如果我们使用 DataTable.Load(),那么我们不需要使用 rdr.NextResult(),因为这是隐式处理的。【参考方案3】:

我以 Pranay Rana 的回答为基础,因为我喜欢让它尽可能小。

string rslt = "";
using (SqlDataReader dr = cmd.ExecuteReader())

    do
    
        while (dr.Read())
        
            rslt += $"ReqID: dr["REQ_NR"], Shpr: dr["SHPR_NR"], MultiLoc: dr["MULTI_LOC"]\r\n";
        
     while (dr.NextResult());

【讨论】:

【参考方案4】:

这个问题很老,但我发现答案不正确。 这是我的做法:

        List<DataTable> dataTables = new();
        using IDataReader dataReader = command.ExecuteReader();
        do
        
            DataTable dataTable = new();
            dataTable.Load(dataReader);
            dataTables.Add(dataTable);
        
        while (!dataReader.IsClosed);

【讨论】:

以上是关于DataReader 中的倍数表的主要内容,如果未能解决你的问题,请参考以下文章

DataReader 循环查询中的 C# MySQL 查询

ADO.NET 四(DataReader)

DataSet和DataReader问题

如果列中的前一个单元格为空,DataReader 不会在 Excel 单元格中看到数据

DataReader 中的 DataReader

Azure 表查询:System.InvalidOperationException:“已经有一个打开的 DataReader 与此命令关联,必须先关闭。”