可能重复:
如何在c#中高效地从SQL数据读取器写入文件?
我目前正在尝试创建一个使用只读访问的web应用程序,允许用户从我们的数据库下载大型文件。该表中有400000条记录,导出时会生成一个50MB.csv文件。
在SQL服务器上运行语句"SELECT*FROM[table]"大约需要7秒,在我的web应用程序(托管在另一台服务器上)上运行大约需要33秒。这是将所有数据读取到System.data.SqlClient.SqlDataReader对象中。
我的问题是,我无法将SqlDataReader转换为.csv文件。将SqlDataReader的每一行转换为一个字符串并逐行将该字符串输出到文件中几乎需要2个小时,这是不可接受的。下面是我用来在web应用程序的服务器上创建文件的代码:
while (rdr.Read())
{
string lineout = "";
for (int index = 0; index < rdr.FieldCount; index++)
lineout += rdr[index].ToString().Replace(',', ' ') + ',';
write(lineout, filename); //uses StreamWriter.WriteLine()
}
必须有更好的方法。我环顾四周,看到了很多建议,这些建议基本上是建议您通过以上操作创建一个文件。这适用于较小的桌子,但不是我们每天使用的两个真正大的桌子。有人能把我推向正确的方向吗?
您可以尝试使用StringBuilder
构建lineout
,而不是手动连接字符串:
//you can test whether it makes any difference in performance declaring a single
//StringBuilder and clearing, or creating a new one per loop
var sb = new StringBuilder();
while (rdr.Read())
{
for (int index = 0; index < rdr.FieldCount; index++)
sb.Append(rdr[index].ToString().Replace(',', ' ').Append(',');
write(sb.ToString(), filename); //uses StreamWriter.WriteLine()
sb.Clear();
}
或者,尝试直接写入文件,避免首先在内存中生成每一行:
//assume a StreamWriter instance has been created called sw...
while (rdr.Read())
{
for (int index = 0; index < rdr.FieldCount; index++)
{
sw.Write(rdr[index].ToString().Replace(',', ' ');
sw.WriteLine(",");
}
}
//flush and close stream