0

重複の可能性:
c#でSQLデータリーダーからファイルに効率的に書き込む方法は?

現在、読み取り専用アクセスを使用して、ユーザーがデータベースから大きなファイルをダウンロードできるようにするWebアプリケーションを作成しようとしています。問題のテーブルには400,000レコードが含まれており、エクスポート時に50MBの.csvファイルが生成されます。

SQLサーバーでステートメント「SELECT*FROM [table]」を実行するには約7秒かかり、(別のサーバーでホストされている)Webアプリケーションから実行するには約33秒かかります。これは、すべてのデータをSystem.Data.SqlClient.SqlDataReaderオブジェクトに読み込んでいます。

私の問題は、SqlDataReaderを.csvファイルに変換するのに途方に暮れていることです。SqlDataReaderの各行を文字列に変換し、その文字列を1行ずつファイルに出力するには、ほぼ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()
    }

より良い方法が必要です。私は周りを見回して、ファイルを作成するために上記を実行することを本質的に推奨する多くの提案を見ました。これは小さなテーブルではうまく機能しますが、私たちが毎日使用する2つの本当に大きなテーブルでは機能しません。誰かが私に正しい方向へのプッシュを与えることができますか?

4

1 に答える 1

5

文字列を手動で連結するのではなく、lineoutを使用してビルドしてみることができます。StringBuilder

//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
于 2013-02-04T21:29:10.777 に答える