Best practice for reusing SqlConnection

后端 未结 5 2030
误落风尘
误落风尘 2021-01-17 09:43

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

相关标签:
5条回答
  • 2021-01-17 10:19

    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.

    0 讨论(0)
  • 2021-01-17 10:22

    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]);
                    }
                }
            });
    
    0 讨论(0)
  • 2021-01-17 10:28

    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.

    0 讨论(0)
  • 2021-01-17 10:32

    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.

    0 讨论(0)
  • 2021-01-17 10:42

    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();
    
    0 讨论(0)
提交回复
热议问题