簡體   English   中英

使用帶有connection.open的語句

[英]using statement with connection.open

我正在查看一些代碼並與同事討論。

特別是一段看起來像這樣的代碼。

    [Test]
    public void TestNormalWay()
    {
        using(var cn = GetConnection())
        {
            cn.Open();
            // do stuff
        }
    }

問題出現了:

“為什么不將cn.Open移動到GetConnection方法中。”

我說如果“打開”拋出一個異常處理就不會被調用。 他的回答是

“那么什么。連接沒有打開,為什么需要關閉(或處理)?”

對我來說,這只是一個不想知道我是否需要處理/關閉的問題所以我會重復cn.Open代碼而不是將其移動到共享函數中。

它很有趣......所以我在SQL Server連接池(ADO.NET)上做了一些閱讀

對我來說,目前尚不清楚是否存在調用cn.Open並拋出異常需要調用dispose的場景。

所以在下面的例子中,“TestNormalWay”和“WhyNotDoItThisWay”之間是否存在任何差異

    protected static DbConnection GetConnection()
    {
        DbConnection cn = new SqlConnection("SomeConnecitonstring... ");
        return cn; 
    }

    protected static DbConnection GetConnectionDangerousVersion()
    {
        DbConnection cn = new SqlConnection("SomeConnecitonstring... ");
        cn.Open();  // this will throw.. .dispose not called
        return cn; 
    }

    [Test]
    public void TestNormalWay()
    {
        using(var cn = GetConnection())
        {
            cn.Open();
            // do stuff
        }
    }

    [Test]
    public void WhyNotDoItThisWay()
    {
        using(var cn = GetConnectionDangerousVersion())
        {
            // do stuff
        }
    }

您編寫代碼的方式總是希望在創建連接后立即打開連接,因此沒有任何區別。

但是,您可以多次打開和關閉連接,並且在設計的代碼中有很大的不同。

我可能想編寫一些代碼,其中我有一個長時間運行的例程,它接受一個連接對象並隨着時間的推移打開並關閉它。 例程可能不關心連接對象是如何創建的。 因此,將創建連接的行為與打開和關閉它的行為分開是有利的。

關於資源管理問題,我同意這不是問題。 創建SQL連接對象本身並不會鎖定任何資源,而是打開它獲取池化連接的行為。 如果open返回異常,我認為假設沒有打開連接是合理的。

我傾向於只返回SqlConnection的實例而不在方法中調用Open() 如果需要,應該這樣做。 您的實用程序功能不需要它。

其中一個原因是,有些對象需要SqlConnection ,但不一定需要打開它們。 例如, SqlDataAdapter接受SqlConnection ,並在其自身內處理它的打開和關閉。 當然,你可以在傳遞之前打開一個連接,但是你必須明確地關閉它。

回過頭幾步,調用代碼應該負責處理與SqlConnection完全相關的操作。

您可以在第二個“危險”版本中圍繞.Open()調用放置一個try / catch,這樣如果它在打開時拋出異常仍然處理連接。

在SqlConnection的內部達到頂峰之后,我幾乎確信這無關緊要。 快速測試似乎證實了這一點:

static void Main( string[] args )
{
   Func<SqlConnection> getConnection =
            () =>
               {
                  var connection =
                     new SqlConnection(
                        "Initial Catalog=myDatabase;Server=(local);Username=bogus;password=blah;Connect Timeout=10;" );

                  connection.Open();
                  return connection;
               };

   while(true)
   {
      try
      {
         using( var connection = getConnection() )
         {
            var cmd = new SqlCommand( "SELECT 1", connection ) {CommandType = CommandType.Text};
            cmd.ExecuteNonQuery();
         }
      }
      catch ( Exception )
      {
         // ignore exception
      }
   }
}

我把這個代碼運行了幾分鍾,並附帶了一個分析器。 它不僅運行速度很快,而且還沒有泄漏任何內存。 這讓我很有信心在GetConnection方法中打開連接是可以的。

當然,此處發布的所有其他論點仍然有效; 如果你要立即使用它,你應該只打開連接。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM