none
請問 DbConnection 重複使用與立即釋放的管理方式 RRS feed

  • 問題

  • 印象中普遍情況下,都是立即建立 Connection 執行 SQL 指令後後就釋放資源:
    using (SqlConnection connection = new SqlConnection(connectionString))
    {
          connection.Open();
          // Do work here; connection closed on following line.
    }

    如果我想要外部傳入 IDbConnection 時,就視為需要可被重複使用連接,由外部管理連線資源,
    若外部沒有傳入 IDbConnection 時,視為當下建立連接,並執行完後釋放,
    請問我下面這樣寫的話,是符合我上述問題的良好做法嗎?
    public class DbConnectionTestSample
    {
        private IDbConnection _externalConnection = null;
        public DbConnectionTestSample(IDbConnection externalConnection = null)
        {
            _externalConnection = externalConnection;
        }
        private bool IsOneTime => _externalConnection == null;
        private IDbConnection CreateConnection() => new SqlConnection("...connectionString....");

        protected IDbConnection GetConnection() => _externalConnection ?? CreateConnection();

        public int Execute(string sql, object param = null)
        {
            var conn = GetConnection();
            try
            {
                return conn.Execute( sql, param)
            }
            finally
            {
                if (IsOneTime)
                    conn.Close();
                else
                    conn.Dispose();
            }
        }
        public IEnumerable<T> Query<T>(string sql, object param = null)
        {
            var conn = GetConnection();
            try
            {
                return conn.Query<T>( sql, param)
            }
            finally
            {
                if (IsOneTime)
                    conn.Close();
                else
                    conn.Dispose();
            }
        }
    }

    2016年12月14日 上午 03:07

解答

  • .NET平台的連線共用區(Connection Pool)預設支援重覆使用連接, 不需要另外處理, 請參考:

    Understanding Connection Pooling in .NET

    • 已標示為解答 503 2016年12月14日 下午 02:58
    2016年12月14日 上午 03:36
  • http://stackoverflow.com/questions/17168839/what-is-the-difference-between-connection-close-and-connection-dispose

    有些控制 connection 的方式,您可以使用一些 framework 來達到你的需求,例如 spring.net

    您需要從外部傳入 connection 是因為控制 交易嗎 ? 


    亂馬客blog: http://www.dotblogs.com.tw/rainmaker/

    • 已標示為解答 503 2016年12月14日 下午 02:59
    2016年12月14日 上午 06:28
  • 就 SqlConnection 的角度,只要下了 Close(),不用管 SQL Server connection pool 有沒有最後釋放資源,也不關程式的事。

    使用 using 是因為它會在內部對 Connection 執行關閉,但除非程式中有用到其他資源,否則 Dispose() 也只是對 SqlConnection 內部做,和程式也沒什麼直接關係。

    程式只要在該放掉 Connection 的時候下 Close(),或是直接用 using 包起來就可以了。


    強力監督SQL Injection問題!!

      • 小朱的技術隨手寫:http://www.dotblogs.com.tw/regionbbs/
      • 雲端學堂Facebook: http://www.facebook.com/studyazure

    • 已標示為解答 503 2016年12月14日 下午 02:58
    2016年12月14日 上午 09:33
    版主

所有回覆

  • 印象中普遍情況下,都是立即建立 Connection 執行 SQL 指令後後就釋放資源:
    using (SqlConnection connection = new SqlConnection(connectionString))
    {
          connection.Open();
          // Do work here; connection closed on following line.
    }

    如果我想要外部傳入 IDbConnection 時,就視為需要可被重複使用連接,由外部管理連線資源,
    若外部沒有傳入 IDbConnection 時,視為當下建立連接,並執行完後釋放,
    請問我下面這樣寫的話,是符合我上述問題的良好做法嗎?
    public class DbConnectionTestSample
    {
        private IDbConnection _externalConnection = null;
        public DbConnectionTestSample(IDbConnection externalConnection = null)
        {
            _externalConnection = externalConnection;
        }
        private bool IsOneTime => _externalConnection == null;
        private IDbConnection CreateConnection() => new SqlConnection("...connectionString....");

        protected IDbConnection GetConnection() => _externalConnection ?? CreateConnection();

        public int Execute(string sql, object param = null)
        {

            var conn = GetConnection();

            if (conn.State == ConnectionState.Closed) conn.Open();

            try
            {
                return conn.Execute( sql, param)
            }
            finally
            {
                if (IsOneTime)
                    conn.Close();
                else
                    conn.Dispose();
            }
        }
        public IEnumerable<T> Query<T>(string sql, object param = null)
        {

            var conn = GetConnection();

            if (conn.State == ConnectionState.Closed) conn.Open();

            try
            {
                return conn.Query<T>( sql, param)
            }
            finally
            {
                if (IsOneTime)
                    conn.Close();
                else
                    conn.Dispose();
            }
        }
    }

    忘了補上 Open,不好意思

    if (conn.State == ConnectionState.Closed) conn.Open(); 

    2016年12月14日 上午 03:20
  • .NET平台的連線共用區(Connection Pool)預設支援重覆使用連接, 不需要另外處理, 請參考:

    Understanding Connection Pooling in .NET

    • 已標示為解答 503 2016年12月14日 下午 02:58
    2016年12月14日 上午 03:36
  • 感謝!更深認識Connection Pooling,

    請問 http://aspalliance.com/1099_Understanding_Connection_Pooling_in_NET.3

    中的 Listing 4 只用了 Close(),沒有使用 Dispose() 對資源釋放上會有什麼影響嗎?


    SqlConnection sqlConnection = new SqlConnection(connectionString);
    try
    {
      sqlConnection.Open();
      //Some Code
    }
     
    finally
    {
      sqlConnection.Close();
    }

    重複使用這一詞我提問錯了,

    修正為若外部有傳入連線物件,則使用同一個外部傳入的連線操作(給予需要同一個連線操作的用途),

    如果沒有外部傳入連線物件,則當下操作 Execute 或 Query 都是立即建立新連線與釋放,

    請問以這個用途是否是良好的做法?


    2016年12月14日 上午 05:49
  • http://stackoverflow.com/questions/17168839/what-is-the-difference-between-connection-close-and-connection-dispose

    有些控制 connection 的方式,您可以使用一些 framework 來達到你的需求,例如 spring.net

    您需要從外部傳入 connection 是因為控制 交易嗎 ? 


    亂馬客blog: http://www.dotblogs.com.tw/rainmaker/

    • 已標示為解答 503 2016年12月14日 下午 02:59
    2016年12月14日 上午 06:28
  • @亂馬克

    記得是有需要用 Temporary table,故設計一個外部傳入的連線物件。

    ---

    我先做個小結,

    只使用 Close() 只能將連線放回 .NET Connection Pool,但還有其他資源尚未釋放,所以不能單純 Close(),

    確定該連線後面沒要繼續使用後,就一定要使用 using 或 Dispose() 才是最佳釋放資源的作法對嗎?


    2016年12月14日 上午 08:12
  • 就 SqlConnection 的角度,只要下了 Close(),不用管 SQL Server connection pool 有沒有最後釋放資源,也不關程式的事。

    使用 using 是因為它會在內部對 Connection 執行關閉,但除非程式中有用到其他資源,否則 Dispose() 也只是對 SqlConnection 內部做,和程式也沒什麼直接關係。

    程式只要在該放掉 Connection 的時候下 Close(),或是直接用 using 包起來就可以了。


    強力監督SQL Injection問題!!

      • 小朱的技術隨手寫:http://www.dotblogs.com.tw/regionbbs/
      • 雲端學堂Facebook: http://www.facebook.com/studyazure

    • 已標示為解答 503 2016年12月14日 下午 02:58
    2016年12月14日 上午 09:33
    版主