我的问题是如何在C#中使用SqlDataReader
获取查询返回的行数。我已经看到了一些关于此的答案,但没有一个明确定义,除了一个声明用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
}
答案 0 :(得分:91)
只有两个选项:
通过阅读所有行来找出(然后你可以存储它们)
事先运行专门的SELECT COUNT(*)查询。
两次通过DataReader循环非常昂贵,您必须重新执行查询。
并且(感谢Pete OHanlon)当您使用具有Snapshot隔离级别的事务时,第二个选项仅是并发安全的。
由于您最终想要将所有行存储在内存中,唯一明智的选择是读取灵活存储(List<>
或DataTable
)中的所有行,然后将数据复制到您的任何格式想。内存中的操作总是更有效率。
答案 1 :(得分:8)
如果您不需要检索所有行并且想要避免进行双重查询,您可以尝试这样的事情:
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();
}
您可能必须添加一个事务,不确定重复使用相同的命令会自动在其上添加一个事务......
答案 2 :(得分:6)
如上所述,数据集或类型化数据集可能是一个很好的临时结构,您可以使用它来进行过滤。 SqlDataReader旨在非常快速地读取数据。当你在while()循环中时,你仍然连接到数据库,它正在等待你做任何你正在做的事情,以便在它继续前读取/处理下一个结果。在这种情况下,如果您提取所有数据,关闭与数据库的连接并“离线”处理结果,您可能会获得更好的性能。
人们似乎讨厌数据集,所以上面也可以用强类型对象的集合来完成。
答案 3 :(得分:4)
您无法直接从数据读取器获取行数,因为它就是所谓的firehose游标 - 这意味着根据正在执行的读取逐行读取数据。我建议不要对数据进行2次读取,因为在进行2次读取之间数据有可能发生变化,因此你会得到不同的结果。
您可以做的是将数据读入临时结构,并使用它代替第二次读取。或者,您需要更改检索数据的机制,并使用类似DataTable的内容。
答案 4 :(得分:2)
完成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();
}
答案 5 :(得分: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;
}