9

sqlWrite.ExecuteNonQuery();数秒で 200 個の挿入クエリを実行した後、コードでエラーが発生することに気付きました。usingこれにより、リソースが適切に再利用され、何もする必要がなくなると常に考えていました。このエラーが発生するのはこれが初めてで、SQL/C# をほぼ 3 年間、さまざまなことを行ってきました。

using (SqlConnection varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetails)) 
{
    using (var sqlWrite = new SqlCommand(preparedCommand, varConnection)) 
    {
        sqlWrite.Parameters.AddWithValue("@var_agr_fname", var_agr_fname == "" ? (object) DBNull.Value : var_agr_fname);
        sqlWrite.ExecuteNonQuery();
    }
}


public static SqlConnection sqlConnectOneTime(string varSqlConnectionDetails)
{
    var sqlConnection = new SqlConnection(varSqlConnectionDetails);
    try
    {
        sqlConnection.Open();
    }
    catch
    {
        DialogResult result = MessageBox.Show(new Form {TopMost = true},
                                              "Błąd połączenia z bazą danych. Czy chcesz spróbować nawiązac połączenie ponownie?",
                                              "Błąd połączenia (000001)",
                                              MessageBoxButtons.YesNo,
                                              MessageBoxIcon.Stop);
        if (result == DialogResult.No)
        {
            if (Application.MessageLoop)
            {
                Application.Exit(); // Use this since we are a WinForms app
            }
            else
            {
                Environment.Exit(1); // Use this since we are a console app
            }
        }
        else
        {
            sqlConnection = sqlConnectOneTime(varSqlConnectionDetails);
        }
    }
    return sqlConnection;
}

エラーメッセージ:A transport-level error has occurred when sending the request to the server. (provider: Shared Memory Provider, error: 0 - No process is on the other end of the pipe.)

このエラーのアドバイスを考慮してSqlConnection.ClearAllPools();、接続が適切にリセットまたは破棄されていることを確認するために使用する必要があります。だから私はそれを使うことができますが、問題はそれをいつどこで使うかです。制限が破られるかどうかを知る方法は?どこが限界?50 / 150 / 200 ? または、ループで毎回使用する必要がありますか?

4

3 に答える 3

5

まず、このコードはひどいものです。UI とデータ接続の作成を混在させています。さらに、catchセクション内にダイアログ ウィンドウを表示し、再帰呼び出しを行います。これは非常に厄介で、それ自体がエラーや予期しない動作につながる可能性があります。また、(元の) 書式設定により、読みにくくなっています。厳しいコメントで申し訳ありませんが、このコードを再設計する必要があります。

それ以外は、コードは正常に動作するはずですが、No process is on the other end of the pipe.エラーが発生する場合は、データベースや SQL Server に何か問題があることを意味します。詰まっているようで、それ以上の接続を受け入れません。短時間で挿入のバッチを実行する場合は、可能であれば 1 つの接続で実行してください。ClearAllPools何か問題が発生したときに回復する方法であり、それを隠すのではなく、それが何であるかを知ることが最善です. 歯が痛いのにパラセタモールを飲んで、歯医者に行かないようなものです。

もう 1 つのことは、複数の SqlConnections を使用すると、接続ごとに個別のトランザクションが作成されることです。これにより、SQL Server に負荷がかかりますが、1 秒あたり確実に数百を超えるトランザクションを実行できます。

また、トランスポートを名前付きパイプと TCP に変更して、何か変更があるかどうかを確認することもできます。

于 2012-04-04T22:37:49.907 に答える
4

「1回以上使用して再利用する方法があります。接続の確立(またはすでに接続されている接続の使用)からプールへの接続の返却まで、すべてを行います。これらは私が得たアドバイスです。このように接続が開いている場合は常に再利用し、閉じている場合は常に開いています。」

これは、接続プールを再発明したようです。接続が閉じている場合は常に再利用し、開いている場合は再利用できません。

したがって、catchブロックの接続を閉じます。

public static SqlConnection sqlConnectOneTime(string varSqlConnectionDetails) {
    var sqlConnection = new SqlConnection(varSqlConnectionDetails);
    try {
        sqlConnection.Open();
    } catch {
        //log and
        sqlConnection.Close();
        throw
    }
    return sqlConnection;
}

編集:正直なところ、私はそのようなファクトリメソッドをまったく使用しません。これらは、再現不可能なエラーの原因にすぎません。使用している接続を作成して開くのに、何がそんなに時間がかかりますか?

using(SqlConnection varConnection = new SqlConnection(Locale.sqlDataConnectionDetails)) {
    using (var sqlWrite = new SqlCommand(preparedCommand, varConnection)) {
        sqlWrite.Parameters.AddWithValue("@varSecus_agr_fname", varSecus_agr_fname == "" ? (object) DBNull.Value : varSecus_agr_fname);
        varConnection.Open();
        sqlWrite.ExecuteNonQuery();
    }
}

最初の2つのリンクは、リンクされた質問(受け入れられた回答ではありません)からのものです。これらも役立つ場合があります。

于 2012-04-04T22:04:24.027 に答える
0

これらの 2 つのエラー:

リクエストをサーバーに送信するときにトランスポート レベルのエラーが発生しました。(プロバイダー: TCP プロバイダー、エラー: 0 - 既存の接続がリモート ホストによって強制的に閉じられました。)

リクエストをサーバーに送信するときにトランスポート レベルのエラーが発生しました。(プロバイダー: 共有メモリ プロバイダー、エラー: 0 - パイプの反対側にプロセスがありません。)

1900 年より前の日付で SQL に挿入される DateTime 値に関連していました。ここでのマイクロソフトのルールは..SQLのDateTime値に1900年未満のDateTime値を格納しないでください。代わりに文字列を使用してください...

于 2012-04-05T08:30:26.283 に答える