如何在 C# 中使用 SqlDataReader 获取行数
我的问题是如何在 C# 中使用 SqlDataReader
获取查询返回的行数。我已经看到了一些关于此问题的答案,但没有一个明确定义,除了一个声明使用 Read() 方法执行 while 循环并增加计数器的答案。
我的问题是,我试图填充一个多维数组,第一行是列标题名称,之后的每一行都是行数据。
我知道我可以将数据转储到列表控件中而不用担心它,但为了我自己的个人启发,我还想在选择时将数据拉入和拉出数组,并以不同的格式显示它。
所以我认为我不能执行 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
}
My question is how to get the number of rows returned by a query using SqlDataReader
in C#. I've seen some answers about this but none were clearly defined except for one that states to do a while loop with Read()
method and increment a counter.
My problem is that I am trying to fill a multi-dimensional array with the first row being the column header names and every row after that to the be the row data.
I know that I can just dump the stuff in a List control and not worry about it, but for my own personal edification and I would also like to pull the data in and out of the array as I choose and display it in different formats.
So I think I can't do the Read()
and then increment ++ way because that means that I would have to open Read()
and then open Read()
again to get amount of rows and then column data.
Just a small example of what I'm talking about:
int counter = 0;
while (sqlRead.Read())
{
//get rows
counter++
}
and then a for loop to run through the columns and pop
something.Read();
int dbFields = sqlRead.FieldCount;
for (int i = 0; i < dbFields; i++)
{
// do stuff to array
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
只有两个选项:
通过读取所有行来查找(然后您也可以存储它们)
运行预先专门的 SELECT COUNT(*) 查询。
执行两次 DataReader 循环确实非常昂贵,您必须重新执行查询。
并且(感谢 Pete OHanlon),只有当您使用具有快照隔离级别的事务时,第二个选项才是并发安全的。
由于您最终希望将所有行存储在内存中,唯一明智的选择是读取灵活存储(
List<>
或DataTable
)中的所有行,然后复制将数据转换为您想要的任何格式。内存中的操作总是会更加高效。There are only two options:
Find out by reading all rows (and then you might as well store them)
run a specialized SELECT COUNT(*) query beforehand.
Going twice through the DataReader loop is really expensive, you would have to re-execute the query.
And (thanks to Pete OHanlon) the second option is only concurrency-safe when you use a transaction with a Snapshot isolation level.
Since you want to end up storing all rows in memory anyway the only sensible option is to read all rows in a flexible storage (
List<>
orDataTable
) and then copy the data to any format you want. The in-memory operation will always be much more efficient.如果您不需要检索所有行并希望避免进行双重查询,您可能可以尝试类似的操作:
您可能必须添加一个事务,不确定重用相同的命令是否会自动在其上添加事务。 ..
If you do not need to retrieve all the row and want to avoid to make a double query, you can probably try something like that:
You may have to add a transaction not sure if reusing the same command will automatically add a transaction on it...
正如其他人所说,数据集或类型化数据集可能是一个很好的临时结构,您可以用它来进行过滤。 SqlDataReader 旨在非常快速地读取数据。当您处于 while() 循环中时,您仍然连接到数据库,并且它正在等待您执行正在执行的操作,以便在继续操作之前读取/处理下一个结果。在这种情况下,如果提取所有数据、关闭与数据库的连接并“离线”处理结果,您可能会获得更好的性能。
人们似乎讨厌数据集,因此上述操作也可以通过强类型对象的集合来完成。
As others have said, a dataset or typed dataset might be a good temporary structure which you could use to do your filtering. A SqlDataReader is meant to read the data very quickly. While you are in the while() loop you are still connected to the DB and it is waiting for you to do whatever you are doing in order to read/process the next result before it moves on. In this case you might get better performance if you pull in all of the data, close the connection to the DB and process the results "offline".
People seem to hate datasets, so the above could be done with a collection of strongly typed objects as well.
您无法直接从数据读取器获取行数,因为它是所谓的消防游标 - 这意味着数据是根据正在执行的读取逐行读取的。我建议不要对数据进行两次读取,因为两次读取之间数据可能会发生变化,因此您会得到不同的结果。
您可以做的是将数据读入临时结构,并使用它代替第二次读取。或者,您需要更改检索数据的机制并使用 DataTable 之类的东西。
You can't get a count of rows directly from a data reader because it's what is known as a firehose cursor - which means that the data is read on a row by row basis based on the read being performed. I'd advise against doing 2 reads on the data because there's the potential that the data has changed between doing the 2 reads, and thus you'd get different results.
What you could do is read the data into a temporary structure, and use that in place of the second read. Alternatively, you'll need to change the mechanism by which you retrieve the data and use something like a DataTable instead.
完成坑答案并获得更好的性能:
在一个查询中获取所有内容并使用 NextResult 方法。
to complete of Pit answer and for better perfromance :
get all in one query and use NextResult method.
当我需要返回最佳结果但又想获取与查询匹配的总行数时,我还面临这样的情况。我终于找到了这个解决方案:
I also face a situation when I needed to return a top result but also wanted to get the total rows that where matching the query. i finaly get to this solution: