104

我的问题是如何使用SqlDataReaderC# 获取查询返回的行数。我已经看到了一些关于此的答案,但没有一个明确定义,除了一个声明使用Read()方法执行 while 循环并增加计数器的答案。

我的问题是我试图填充一个多维数组,第一行是列标题名称,之后的每一行都是行数据。

我知道我可以将内容转储到 List 控件中而不用担心,但是为了我自己的个人启迪,我还想在选择时将数据拉入和拉出数组并以不同的格式显示。

所以我认为我不能执行Read()然后递增 ++ 的方式,因为这意味着我必须打开Read()然后Read()再次打开才能获取行数和列数据。

只是我正在谈论的一个小例子:

int counter = 0;    

while (sqlRead.Read())
{
    //get rows
    counter++
}

然后一个 for 循环遍历列并弹出

something.Read();

int dbFields = sqlRead.FieldCount;

for (int i = 0; i < dbFields; i++)
{
   // do stuff to array
}
4

6 回答 6

102

只有两个选项:

  • 通过阅读所有行找出(然后你也可以存储它们)

  • 事先运行专门的 SELECT COUNT(*) 查询。

两次通过 DataReader 循环非常昂贵,您将不得不重新执行查询。

并且(感谢 Pete OHanlon)第二个选项仅在您使用具有快照隔离级别的事务时是并发安全的。

由于您希望最终将所有行存储在内存中,唯一明智的选择是读取灵活存储(List<>DataTable)中的所有行,然后将数据复制为您想要的任何格式。内存中的操作总是会更有效率。

于 2009-09-05T13:25:53.740 回答
10

如果您不需要检索所有行并希望避免进行双重查询,您可以尝试这样的事情:

using (var sqlCon = new SqlConnection("Server=127.0.0.1;Database=MyDb;User Id=Me;Password=glop;"))
      {
        sqlCon.Open();

        var com = sqlCon.CreateCommand();
        com.CommandText = "select * from BigTable";
        using (var reader = com.ExecuteReader())
        {
            //here you retrieve what you need
        }

        com.CommandText = "select @@ROWCOUNT";
        var totalRow = com.ExecuteScalar();

        sqlCon.Close();
      }

您可能必须添加一个事务,不确定重复使用相同的命令是否会自动在其上添加一个事务......

于 2013-09-11T08:15:34.270 回答
8

如上所述,数据集或类型化数据集可能是一个很好的临时结构,您可以使用它来进行过滤。SqlDataReader 旨在非常快速地读取数据。当您在 while() 循环中时,您仍然连接到数据库,它正在等待您执行您正在做的任何事情,以便在下一个结果继续之前读取/处理它。在这种情况下,如果您拉入所有数据,关闭与数据库的连接并“离线”处理结果,您可能会获得更好的性能。

人们似乎讨厌数据集,因此也可以使用强类型对象的集合来完成上述操作。

于 2009-09-05T13:39:27.583 回答
7

您不能直接从数据读取器获取行数,因为它就是所谓的 firehose 游标——这意味着数据是根据正在执行的读取逐行读取的。我建议不要对数据进行 2 次读取,因为在 2 次读取之间数据可能会发生变化,因此您会得到不同的结果。

您可以做的是将数据读入一个临时结构,并使用它来代替第二次读取。或者,您需要更改检索数据的机制并改用 DataTable 之类的东西。

于 2009-09-05T13:28:44.670 回答
6

完成 Pit 答案并获得更好的性能:一次查询并使用 NextResult 方法。

using (var sqlCon = new SqlConnection("Server=127.0.0.1;Database=MyDb;User Id=Me;Password=glop;"))
{
    sqlCon.Open();
    var com = sqlCon.CreateCommand();
    com.CommandText = "select * from BigTable;select @@ROWCOUNT;";
    using (var reader = com.ExecuteReader())
    {
        while(reader.Read()){
            //iterate code
        }
        int totalRow = 0 ;
        reader.NextResult();
        if(reader.Read()){
            totalRow = (int)reader[0];
        }
    }
    sqlCon.Close();
}
于 2019-01-08T06:39:01.280 回答
1

当我需要返回最佳结果但又想获得与查询匹配的总行数时,我也面临这样的情况。我终于得到了这个解决方案:

   public string Format(SelectQuery selectQuery)
    {
      string result;

      if (string.IsNullOrWhiteSpace(selectQuery.WherePart))
      {
        result = string.Format(
@"
declare @maxResult  int;
set @maxResult = {0};

WITH Total AS
(
SELECT count(*) as [Count] FROM {2}
)
SELECT top (@maxResult) Total.[Count], {1} FROM Total, {2}", m_limit.To, selectQuery.SelectPart, selectQuery.FromPart);
      }
      else
      {
        result = string.Format(
@"
declare @maxResult  int;
set @maxResult = {0};

WITH Total AS
(
SELECT count(*) as [Count] FROM {2} WHERE {3}
)
SELECT top (@maxResult) Total.[Count], {1} FROM Total, {2} WHERE {3}", m_limit.To, selectQuery.SelectPart, selectQuery.FromPart, selectQuery.WherePart);
      }

      if (!string.IsNullOrWhiteSpace(selectQuery.OrderPart))
        result = string.Format("{0} ORDER BY {1}", result, selectQuery.OrderPart);

      return result;
    }
于 2016-01-15T13:51:51.337 回答