Best practice for reusing SqlConnection

风流意气都作罢 提交于 2019-12-23 07:14:35

问题


I've come from Java experience and am trying to start with C#. I've read SqlConnection SqlCommand SqlDataReader IDisposable and I can understand that the best practice to connecting to a DB is wrapping SqlConnection, SqlCommand and SqlDataReader in their own using block.

But in Java we use to encapsulate the connection into a factory method, create it only once, and reuse it for all queries, even multithreaded ones. Only statements and result sets are created for each query and closed ASAP.

Isn't creating a new SqlConnection for each query kinda overkill? Can't it be reused?


回答1:


Creating a new instance of the class SqlConnection does not create a new network connection to SQL Server, but leases an existing connection (or creates a new one). .NET handles the physical connection pooling for you.

When you have finished with your connection (through which you can send multiple queries) just Close() or Dispose() (or use a using{} block preferably).

There is no need, and not good practise, to cache instances of the SqlConnection class.




回答2:


MS SQL server manages connections in it's own connection pool, and they aren't actually disposed. But they are closed so you minimize the network traffic and release the available connections to your server.

Also you should note that if you are using the Linq-To-SQL, the data context will not release the connection until being disposed, so I suggest you just use already working code and do not try to optimize it by yourself.




回答3:


As VMAtm has said, .net Pools the connections on it's own, so it is perfectly ok to recreate them. As such I generally write a wrapper for the whole process like this one.

        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]);
                }
            }
        });



回答4:


To answer your specific question, you can reuse a SqlConnection for each query. Just make sure to close your current query (SqlDataReader, etc.) before you run another one, ie. wrap them in their own using blocks.




回答5:


Yes, you can create a global SqlConnection instance. In my case I use the SqlConnection as member of my DataContext that I access via Singleton.

public class DatabaseDataContext : DataContext
{
    private static DatabaseDataContext instance;
    private SqlConnection sqlConnection;        
    private SqlTransaction sqlTransaction;

    //...

    public static DatabaseDataContext Instance
    {
        get
        {
            return instance ?? (instance = new DatabaseDataContext(connectionString));
        }
        set
        {
            instance = value;
        }
    }
}

You can encapsulate your transactions by closing and opening this connection, i.e.:

DatabaseDataContext.Instance.sqlConnection.Open();

// your transactions...

sqlConnection.Close();

Or you might leave the connection open, but instead specifically begin and end transactions:

DatabaseDataContext.Instance.sqlConnection.Open();

sqlTransaction = sqlConnection.BeginTransaction("Example Insert users");

try{
    // ...your first transaction

    sqlTransaction.Commit();
}
catch{sqlTransaction.Rollback();}

sqlTransaction = sqlConnection.BeginTransaction("Update baked breads");

try{
    // ...your second transaction

    sqlTransaction.Commit();
}
catch{sqlTransaction.Rollback();}

// Close the connection at some point
sqlConnection.Close();


来源:https://stackoverflow.com/questions/27692050/best-practice-for-reusing-sqlconnection

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!