我的问题是如何SqlDataReader
在C#中获取查询返回的行数.我已经看到了一些关于此的答案,但没有明确定义,除了一个声明用Read()
方法做一个while循环并增加一个计数器.
我的问题是我试图填充一个多维数组,第一行是列标题名称,后面的每一行都是行数据.
我知道我可以将这些东西转储到List控件中而不用担心它,但是对于我自己的个人启发,我还想在我选择的时候将数据拉入和拉出阵列,并以不同的格式显示它.
所以我认为我不能这样做Read()
然后增加++方式,因为这意味着我必须打开Read()
然后Read()
再次打开以获得行数然后列数据.
只是我正在谈论的一个小例子:
int counter = 0;
while (sqlRead.Read())
{
//get rows
counter++
}
Run Code Online (Sandbox Code Playgroud)
然后一个for循环运行列和弹出
something.Read();
int dbFields = sqlRead.FieldCount;
for (int i = 0; i < dbFields; i++)
{
// do stuff to array
}
Run Code Online (Sandbox Code Playgroud)
Hen*_*man 93
只有两个选择:
通过阅读所有行找出(然后你也可以存储它们)
事先运行专门的SELECT COUNT(*)查询.
两次通过DataReader循环非常昂贵,您必须重新执行查询.
并且(感谢Pete OHanlon)当您使用具有Snapshot隔离级别的事务时,第二个选项仅是并发安全的.
由于您最终想要将所有行存储在内存中,唯一明智的选择是读取灵活存储(List<>
或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();
}
Run Code Online (Sandbox Code Playgroud)
您可能必须添加一个事务,不确定重用相同的命令是否会自动添加一个事务...
小智 6
如上所述,数据集或类型化数据集可能是一个很好的临时结构,您可以使用它来进行过滤.SqlDataReader旨在非常快速地读取数据.当你在while()循环中时,你仍然连接到数据库,它正在等待你做任何你正在做的事情,以便在它继续前读取/处理下一个结果.在这种情况下,如果您提取所有数据,关闭与数据库的连接并"离线"处理结果,您可能会获得更好的性能.
人们似乎讨厌数据集,所以上面也可以用强类型对象的集合来完成.
您无法直接从数据读取器中获取行数,因为这就是所谓的流水光标(firehose cursor)-这意味着将基于执行的读取逐行读取数据。我建议不要对数据进行2次读取,因为在进行2次读取之间数据可能会发生变化,因此您会得到不同的结果。
您可以做的是将数据读取到一个临时结构中,并用它代替第二次读取。另外,您将需要更改检索数据的机制,并改用DataTable之类的方法。
完成 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();
}
Run Code Online (Sandbox Code Playgroud)