web-dev-qa-db-ja.com

SqlConnectionを「開く/閉じる」または開いたままにしますか?

静的メソッドを備えた単純な静的クラスにビジネスロジックを実装しています。これらの各メソッドは、呼び出されたときにSQL接続を開閉します。

public static void DoSomething(string something)
{
    using (SqlConnection connection = new SqlConnection("..."))
    {
        connection.Open();

        // ...

        connection.Close();
    }
}

しかし、接続を開いたり閉じたりするのを避けると思いますパフォーマンスを保存OleDbConnection class(SqlConnectionについてはわかりません)を使用して、かなり前にいくつかのテストを行いました。

//pass the connection object into the method
public static void DoSomething(string something, SqlConnection connection)
{
    bool openConn = (connection.State == ConnectionState.Open);
    if (!openConn)
    {
        connection.Open();
    }

    // ....

    if (openConn) 
    {
        connection.Close();
    }
}

質問は-メソッド(a)またはメソッド(b)を選択する必要がありますか?別のstackoverflowの質問で、接続プーリングがパフォーマンスを節約したことを読んで、私はまったく気にする必要はありません...

PS。これはASP.NETアプリです-接続はWebリクエスト中にのみ存在します。 Winアプリやサービスではありません。

102
Alex

オプションaに固定

接続プーリングはあなたの友達です。

74
Adriaan Stander

毎回、方法(a)を使用します。アプリケーションのスケーリングを開始すると、状態を処理するロジックは、そうしないと本当に苦痛になります。

接続プーリングは、錫で言うことを行います。アプリケーションのスケーリング時に何が起こるか、接続のオープン/クローズ状態を手動で管理するのがどれほど難しいかを考えてください。接続プールは、これを自動的に処理する素晴らしい仕事をします。パフォーマンスが心配な場合は、何もブロックされないように何らかのメモリキャッシュメカニズムを検討してください。

77
WeNeedAnswers

接続が完了するとすぐに常に接続を閉じます。そのため、基になるデータベース接続はプールに戻り、他の呼び出し元が利用できるようになります。接続プーリングは非常に最適化されているため、そうすることによる顕著なペナルティはありません。アドバイスは基本的にトランザクションの場合と同じです-完了したら短くして閉じます。

複数の接続を使用するコードを中心に単一のトランザクションを使用することでMSDTCの問題が発生すると、より複雑になります。この場合、実際には接続オブジェクトを共有し、トランザクションが完了してから閉じる必要があります。

ただし、ここでは手作業で作業しているため、DataSet、Linq to SQL、Entity Framework、NHibernateなど、接続を管理するツールを調査することをお勧めします。

28
Neil Barnwell

免責事項:私はこれが古いことを知っていますが、この事実を示す簡単な方法を見つけたので、2セント分の価値を投入しています。

プーリングが本当に速くなると信じられない場合は、これを試してください:

以下をどこかに追加します。

using System.Diagnostics;
public static class TestExtensions
{
    public static void TimedOpen(this SqlConnection conn)
    {
        Stopwatch sw = Stopwatch.StartNew();
        conn.Open();
        Console.WriteLine(sw.Elapsed);
    }
}

Open()へのすべての呼び出しをTimedOpen()に置き換えて、プログラムを実行します。これで、各接続文字列に対して、コンソール(出力)ウィンドウには1つの長時間実行されたオープンがあり、veryの束が高速で開きます。

それらにラベルを付けたい場合は、WriteLineへの呼び出しにnew StackTrace(true).GetFrame(1) +を追加できます。

12
Crisfole

物理接続と論理接続には違いがあります。 DbConnectionは一種の論理接続であり、Oracleへの基礎となる物理接続を使用します。 DbConnectionを閉じたり開いたりしてもパフォーマンスには影響しませんが、コードはクリーンで安定します。この場合、接続リークは不可能です。

また、dbサーバーでの並列接続に制限がある場合についても覚えておく必要があります。これを考慮して、接続を非常に短くする必要があります。

接続プールを使用すると、接続状態のチェックから解放されます-それらを開いて使用し、すぐに閉じます。

7
Tony Kh

通常、トランザクションごとに1つの接続を維持する必要があります(並列計算なし)

たとえば、ユーザーが充電アクションを実行するとき、アプリケーションは最初にユーザーの残高を見つけて更新する必要があり、同じ接続を使用する必要があります。

Ado.netに接続プールがある場合でも、ディスパッチ接続コストは非常に低くなりますが、再利用接続の方がより適切な選択です。

アプリケーションに接続を1つだけ保持しない理由

クエリまたはコマンドを実行すると接続がブロックされるため、アプリケーションが同時に実行するdb操作は1つだけであるため、パフォーマンスが低下します。

もう1つの問題は、ユーザーが開いているだけで操作は行われていない場合でも、アプリケーションには常に接続があることです。多くのユーザーがアプリケーションを開いている場合、dbサーバーはユーザーがまだ接続していない間にすぐにすべての接続ソースに費用がかかります何でも。

0
ShiningRush