18

私はよくこのようなパターンを使用します。これでいいのか、それともここで適用していないベストプラクティスがあるのか​​ 疑問に思っています.

具体的には、私は疑問に思っています。例外がスローされた場合、finally ブロックにあるコードは、接続が適切に閉じられるようにするのに十分ですか?

public class SomeDataClass : IDisposable
{
    private SqlConnection _conn;

    //constructors and methods

    private DoSomethingWithTheSqlConnection()
    {
        //some code excluded for brevity

        try
        {
            using (SqlCommand cmd = new SqlCommand(SqlQuery.CountSomething, _SqlConnection))
            {
                _SqlConnection.Open();
                countOfSomething = Convert.ToInt32(cmd.ExecuteScalar());
            }
        }
        finally
        {
            //is this the best way?
            if (_SqlConnection.State == ConnectionState.Closed)
                _SqlConnection.Close();
        }

        //some code excluded for brevity
    }

    public Dispose()
    {
        _conn.Dispose();
    }
}
4

9 に答える 9

45

データベース処理コードを「using」内にラップします

using (SqlConnection conn = new SqlConnection (...))
{
    // Whatever happens in here, the connection is 
    // disposed of (closed) at the end.
}
于 2008-09-26T18:46:37.603 に答える
8

.Net Frameworkは、ある理由で接続プールを維持します。信頼してください!:)データベースに接続して接続を解放するためだけに、それほど多くのコードを記述する必要はありません。

'using'ステートメントを使用するだけで、'IDBConnection.Release()'が接続を閉じますのでご安心ください。

非常に手の込んだ「ソリューション」は、バグのあるコードになる傾向があります。シンプルな方がいいです。

于 2008-09-26T18:55:01.047 に答える
5

MSDN Docsはこれをかなり明確にしています...

  • Close メソッドは、保留中のトランザクションをロールバックします。次に、接続を接続プールに解放するか、接続プールが無効になっている場合は接続を閉じます。

おそらく、接続プールを無効にしていない (そして無効にしたくない) ため、「Close」を呼び出した後、プールは最終的に接続の状態を管理します。開いているすべての接続をデータベース サーバー側から見ると混乱する可能性があるため、これは重要な場合があります。


  • アプリケーションは、Close を複数回呼び出すことができます。例外は発生しません。

では、クローズドのテストをわざわざ行う必要はありません。Close() を呼び出すだけです。


  • Close と Dispose は機能的に同等です。

これが、ブロックを使用すると接続が閉じられる 理由です。Dispose の呼び出しを使用します。


  • クラスの Finalize メソッドで、Connection、DataReader、またはその他のマネージド オブジェクトで Close または Dispose を呼び出さないでください。

重要な安全上のヒント。ありがとう、エゴン。

于 2008-09-26T18:55:57.940 に答える
2

私は_SqlConnection.State == ConnectionState.Closedあなたが意味したと推測しています!=

これは確かに機能します。接続オブジェクト自体をusingステートメント内に含めるのがより一般的だと思いますが、何らかの理由で同じ接続オブジェクトを再利用したい場合は、持っているものが適しています。

ただし、必ず変更する必要があるのはDispose()方法です。その時点ですでにファイナライズされている可能性があるため、disposeで接続オブジェクトを参照しないでください。代わりに、推奨されるDisposeパターンに従う必要があります。

于 2008-09-26T18:49:52.993 に答える
1

示されているように、接続クローズコードを「Finally」ブロック内に配置します。最後に、例外がスローされる前にブロックが実行されます。「using」ブロックの使用も同様に機能しますが、明示的な「Finally」メソッドの方が明確です。

ステートメントを使用することは多くの開発者にとって古くからの帽子ですが、若い開発者はそれをすぐに知らないかもしれません。

于 2008-09-26T18:52:21.863 に答える
1

答えについては、この質問を参照してください。

クローズして破棄 - どちらを呼び出すか?

接続の存続期間が単一のメソッド呼び出しである場合はusing、言語の機能を使用して、接続の適切なクリーンアップを確保してください。ブロックは機能的には同じですが、try/finallyより多くのコードが必要になり、IMO は読みにくくなります。接続の状態を確認する必要はありませんDispose。関係なく呼び出すことができ、接続のクリーンアップを処理します。

接続の有効期間が含まれているクラスの有効期間に対応する場合は、 で接続を実装IDisposableしてクリーンアップしDisposeます。

于 2008-09-26T19:02:03.277 に答える
1

とにかくIDisposablesを使用しているので。「using」キーワードを使用できます。これは基本的に、finally ブロックで dispose を呼び出すのと同じですが、見栄えが良くなります。

于 2008-09-26T18:46:46.230 に答える
0

試す必要はありません..最終的には「使用」の周りで、使用は試行です..最終的に

于 2009-02-05T22:17:00.283 に答える
-4

私はこれを提案するかもしれません:


    class SqlOpener : IDisposable
    {
        SqlConnection _connection;

        public SqlOpener(SqlConnection connection)
        {
            _connection = connection;
            _connection.Open();

        }

        void IDisposable.Dispose()
        {
            _connection.Close();
        }
    }

    public class SomeDataClass : IDisposable
    {
        private SqlConnection _conn;

        //constructors and methods

        private void DoSomethingWithTheSqlConnection()
        {
            //some code excluded for brevity
            using (SqlCommand cmd = new SqlCommand("some sql query", _conn))
            using(new SqlOpener(_conn))
            {
                int countOfSomething = Convert.ToInt32(cmd.ExecuteScalar());
            }
            //some code excluded for brevity
        }

        public void Dispose()
        {
            _conn.Dispose();
        }
    }

お役に立てば幸いです:)

于 2008-09-26T18:51:39.323 に答える