【问题标题】:C# - DataReader fails to return multiple result setsC# - DataReader 无法返回多个结果集
【发布时间】:2014-06-26 10:55:58
【问题描述】:

我正在尝试做的类似于 OP 在此处询问的内容:

Multiples Table in DataReader

我正在尝试将一个或多个 SQL 查询的结果存储到单独的数据表中。上述问题方法的问题在于它仅适用于每个结果集中的离散值。最好使用 DataTables Load(reader) 方法将每个结果集存储在单个语句中,而不是遍历 DataReader 的所有列。

在下面的代码中,我有两个 SQL 查询(尽管这应该适用于任意数量的查询),我尝试将其结果存储在临时数据表中,然后存储到数据表列表中。我的代码的问题是它只返回第一个查询的结果集,添加后续查询会引发Reader is closed exception

    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        using (SqlCommand command = new SqlCommand
               ("SELECT TOP 10 Column1, Column2 FROM Table1; SELECT TOP 10 Column1, Column2 FROM Table2", connection))
        {
            connection.Open();

            using (SqlDataReader reader = command.ExecuteReader())
            {
                    while (reader.Read())
                    {
                        tempTable.Reset();
                        tempTable.Load(reader);
                        dataTables.Add(tempTable);
                    }

                    if (reader.NextResult())
                    {
                        while (reader.Read())
                        {
                            tempTable.Reset();
                            tempTable.Load(reader);
                            dataTables.Add(tempTable);
                        }
                    }
            }
        }
    }

我已经为此苦苦挣扎了好几个小时。我不确定 DataTable/DataReader 是否只是针对我的用例设计不佳,或者我在这里缺少一些基本的东西。

【问题讨论】:

  • 你的 reader.NextResult() 应该在你的第一个 while(reader.Read()) 之外
  • 根据您的建议进行了更新。不过,这也会引发“阅读器已关闭异常”。
  • 问题是tempTable.Load(reader)在加载最后一个结果后会自动关闭连接,所以不能在while内嵌入(reader.Read())
  • 如果你还想使用 tempTable.Load(reader),如果你知道你有多少个查询结果,你就可以这样做,在这种情况下你有 2 个,所以你在 for 循环中循环它直到达到结果数
  • 您可以尝试使用SqlDataAdapter 而不是SqlDataReader

标签: c# sqldatareader


【解决方案1】:

DataReader 不适合我的需要,它的使用会导致代码冗长,所以我使用了 Daniel Kelly 建议的 DataAdapter。读取多个结果集的代码现在比较简单:

    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        using (SqlCommand command = new SqlCommand
               ("SELECT TOP 10 Name, [Description] FROM Business; SELECT TOP 10 ConnectionId FROM Connection;SELECT TOP 10 Name FROM Business", connection))
        {
            connection.Open();

                SqlDataAdapter adapter = new SqlDataAdapter(command);
                DataSet set = new DataSet(); 
                adapter.SelectCommand = command;

                //Note here, that the adapter will create multiple tables for each result set
                adapter.Fill(set); 

                foreach (DataTable t in set.Tables)
                {
                    dataTables.Add(t);
                }

                dataTables.Add(tempTable);
        }
    } 

阅读您的 cmets 后,我发现我对 reader.Read() 和 NextResult() 的理解存在缺陷。另外,每次调用 DataReader 的 load 方法时都会关闭 reader 的连接。

感谢大家的 cmets 和建议。我不会接受我自己的答案,因为那会自负。

【讨论】:

  • 我建议将 SqlDataAdapter 的用法包装在 using 块中,因为我相信它实现了 IDisposable
  • 谢谢你,丹尼尔。我已经在我的其他代码中做到了这一点。我上面发布的代码来自一个 hacky 控制台应用程序,我编写它是为了快速解决我的问题。
【解决方案2】:

如果您更喜欢使用 datatable.Load(reader),请尝试以下解决方案:

using (SqlConnection connection = new SqlConnection(connectionString))
        {
            using (SqlCommand command = new SqlCommand
                   ("SELECT TOP 10 Column1, Column2 FROM Table1; SELECT TOP 10 Column1, Column2 FROM Table2", connection))
            {
                connection.Open();
                using (SqlDataReader reader = command.ExecuteReader())
                {
                    bool haveresult = true;
                        while (haveresult)
                        {
                            DataTable tempTable = new DataTable();
                            tempTable.Load(reader);
                            dataTables.Add(tempTable);
                            try
                            {
                                reader.Read();
                            }
                            catch
                            {
                                haveresult = false;
                            }

                        }

                    }

            }
        }

您使用这种方法是因为您无法控制在阅读器获得最后一个结果后何时关闭连接。请注意,这可用于您拥有的任意数量的查询

【讨论】:

  • 在使用DataTable.Load(reader)时,不需要使用reader.NextResult(),reader.Read()会遍历表,自己试试
  • 当然我会尝试,但你是如何创建多个表的。如果读取器在加载后关闭,那么您将如何创建第二个表?
猜你喜欢
  • 2010-09-27
  • 2016-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-30
  • 2010-10-19
相关资源
最近更新 更多