web-dev-qa-db-ja.com

SqlConnectionを再利用するためのベストプラクティス

私はJavaの経験から来て、C#から始めようとしています。読んだ SqlConnection SqlCommand SqlDataReader IDisposable そして接続するためのベストプラクティスを理解できますDBは、SqlConnectionSqlCommand、およびSqlDataReaderを独自のusingブロックでラップしています。

ただし、Javaでは、接続をファクトリメソッドにカプセル化し、1回だけ作成し、マルチスレッドクエリを含むすべてのクエリで再利用します。クエリごとにステートメントと結果セットのみが作成され、できるだけ早く閉じました。

クエリごとに新しいSqlConnectionを作成するのはちょっとやり過ぎではありませんか?再利用できませんか?

12
Hikari

クラスSqlConnectionの新しいインスタンスを作成しても、SQL Serverへの新しいネットワーク接続は作成されませんが、既存の接続がリースされます(または新しい接続が作成されます)。 .NETは、物理接続プールを処理します。

接続(複数のクエリを送信できる)が終了したら、Close()またはDispose()(またはusing{}ブロックが望ましい)。

SqlConnectionクラスのインスタンスをキャッシュする必要はなく、適切な方法でもありません。

28
PhillipH

MS SQLサーバーは、独自の接続プールで接続を管理しますが、実際には破棄されません。ただし、これらは閉じているため、ネットワークトラフィックを最小限に抑え、サーバーへの使用可能な接続を解放します。

また、Linq-To-SQLを使用している場合、データコンテキストは破棄されるまで接続を解放しないため、既に機能しているコードを使用し、自分で最適化しようとしないことをお勧めします。

6
VMAtm

VMAtmが言ったように、.netは接続を独自にプールするので、それらを再作成することはまったく問題ありません。そのため、私は通常、このようなプロセス全体のラッパーを作成します。

        public static void RunWithOpenSqlConnection(string connectionString, Action<SqlConnection> connectionCallBack)
    {
        SqlConnection conn = null;
        try
        {
            conn = new SqlConnection(connectionString);
            connectionCallBack(conn);
        }
        catch (Exception ex)
        {
            //Log Error Here
        }
        finally
        {
            if (conn != null)
                conn.Dispose(); //will close the connection
        }
    }

    public static void ExecuteSqlDataReader(string connectionString, string sqlCommand, Action<SqlDataReader> readerCallBack)
    {
        RunWithOpenSqlConnection(connectionString, delegate(SqlConnection conn)
        {
            SqlCommand cmd = null;
            SqlDataReader reader = null;
            try
            {
                cmd = new SqlCommand(sqlCommand, conn);
                reader = cmd.ExecuteReader();
                readerCallBack(reader);
            }
            catch (Exception ex)
            {
                //Log Error Here
            }
            finally
            {
                if (reader != null)
                    reader.Dispose();
                if (cmd != null)
                    cmd.Dispose();
            }
        });
    }

//Example calling these
            ExecuteSqlDataReader(ConfigurationManager.ConnectionStrings["myConnectionString"].ConnectionString, "Select EmployeeID FROM Employees;", delegate(SqlDataReader reader)
        {
            List<string> employeeIds = new List<string>();
            if (reader.HasRows)
            {
                while(reader.Read())
                {
                    employeeIds.Add((string)reader[0]);
                }
            }
        });
3
Ryan Mann

特定の質問に答えるために、クエリごとにSqlConnectionを再利用できます。別のクエリを実行する前に、必ず現在のクエリ(SqlDataReaderなど)を閉じてください。それらを独自のusingブロックでラップします。

1
ElGavilan