如何在C#中使用SqlDataReader获取行数

我的问题是如何获取在C#中使用SqlDataReader查询返回的行数。 我已经看到了一些关于这个问题的答案,但没有一个被清楚地定义,除了一个声明用Read()方法做一个while循环并增加一个计数器。

我的问题是,我正在尝试填充一个multidimensional array,第一行是列标题名称,然后每行都是行数据。

我知道我可以将这些东西转储到List控件中,而不用担心,但是对于我自己的个人启发,我还想根据需要将数据从数组中取出并以不同的格式显示出来。

所以我认为我不能执行Read()然后递增++方式,因为这意味着我将不得不打开Read() ,然后再次打开Read()以获得大量行数,然后再获取列数据。

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

 int counter = 0; while (sqlRead.Read()) { //get rows counter++ } 

然后一个for循环遍历列和stream行

 something.Read(); int dbFields = sqlRead.FieldCount; for (int i = 0; i < dbFields; i++) { // do stuff to array } 

只有两个select:

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

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

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

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

既然你想最终将所有行存储在内存中,唯一明智的select是读取灵活存储( List<>DataTable )中的所有行,然后将数据复制到所需的任何格式。 内存中的操作将始终更有效率。

关系类/ DataSet是合适的选项。

 using (DataTable dt = new DataTable()) { dt.Load(sqlRead); Console.WriteLine(dt.Rows.Count); } 

根据以上情况,数据集或types化数据集可能是一个很好的临时结构,您可以使用它来进行过滤。 SqlDataReader是为了快速读取数据。 当你在while()循环中时,你仍然连接到数据库,并且它正在等待你做任何你正在做的事情,以便在它继续之前读取/处理下一个结果。 在这种情况下,如果您提取所有数据,则可能会获得更好的性能,closures到数据库的连接并“离线”处理结果。

人们似乎讨厌数据集,所以上面也可以用强types对象的集合来完成。

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

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

如果你不需要检索所有的行,并且想避免做一个双重查询,你可以尝试类似这样的事情:

 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(); } 

你可能不得不添加一个交易不知道如果重复使用相同的命令会自动添加一个交易…

我也遇到了一个情况,当我需要返回一个最好的结果,但也想获得匹配查询的总行数。 我最终得到这个解决scheme:

  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; }