2016-02-29 42 views
0

請在回答之前閱讀完整的問題。我很抱歉,我似乎從來沒有寫過簡短的問題......SQL Server連接超時以及在命令和連接對象中使用語句

我正在支持一個C#內部Web應用程序,該應用程序在Windows Small Business Server 2011 SP1框上運行SQL Server 2008 R2。

我們已經得到了很多SQL的超時最近,這裏有一個例子例外:

System.Web.HttpUnhandledException:類型System.Web.HttpUnhandledException「的異常被拋出。 ---> System.InvalidOperationException:超時過期。在從池中獲取連接之前已超時。發生這種情況的原因可能是因爲所有連接池都在使用中,並且達到最大池大小。 在System.Data.ProviderBase.DbConnectionFactory.GetConnection(的DbConnection owningConnection) 在System.Data.ProviderBase.DbConnectionClosed.OpenConnection(的DbConnection outerConnection,DbConnectionFactory connectionFactory的) 在System.Data.SqlClient.SqlConnection.Open()

我檢查了一些事情,其中​​之一就是代碼如何處理連接和關閉連接。我已經在其他線程中讀過,在你的連接中使用Using語句是足夠的,因爲它「......將try ... finally中的連接創建並最終將連接處理調用放到finally中」。即使發生異常,連接也會關閉。

因此,我同意並使用該方法多年。即使在連接中使用Using語句時,其他人也建議顯式關閉連接。我認爲這將是多餘的......但是,我的問題是關於命令對象。其他人爲這個應用程序編寫了一個大型的db方法庫,並且它們(在所有的db方法中)在使用SqlConnection對象的語句之前聲明瞭SqlCommand對象。他們還在連接使用語句之前將連接對象分配給命令對象。

更好的做法是在連接使用語句中聲明和使用命令對象,並且可以通過另一種方式導致sql連接超時(禁止其他原因的sql連接超時)?拿這個代碼,例如:

​​

也知道調用頁面都嘗試在他們漁獲物和它是錯誤記錄到我們的日誌數據庫的頁面。我們讓異常冒泡到頁面上的調用方法,並在那裏處理。

回答

0

您應該在完成後明確地關閉連接。你從來沒有關閉任何連接,所以在達到連接池限制後,你將會得到錯誤,直到你手動回收池或它自己循環。移動使用塊內的屬性分配塊並執行con.Close(); cmd.Dispose();退回objMusician前:

using (con) 
{ 
    con.Open(); 
    SqlDataReader reader = cmd.ExecuteReader(); 
    if (reader.HasRows) 
    { 
     reader.Read(); 
     objMusician = new Musician((int)reader["id"]); 
     objMusician.Name = (string)reader["name"]; 
    } 

    if objMusician != null) 
    { 
     objMusician.Albums = Albums.GetAlbums((int)objMusician.ID); 
     objMusician.Tours = Tours.GetTours((int)objMusician.ID); 
     objMusician.Interviews = Interviews.GetInterviews((int)objMusician.ID); 
    } 

    con.Close(); 
    cmd.Dispose();   

    return objMusician; 
} 
+0

Using語句應該關閉連接,是不是正確? – Kershaw

+0

另外,主要問題是,如果命令對象在連接使用塊內部聲明和使用?不能這樣做有問題嗎? – Kershaw

+1

'Dispose'關閉連接並將其返回到池中。 –

0

不知道這是否會幫助您的超時問題,但我一直結構類似於下面的,而不是有這個問題我的代碼:

using(var cmd = new SqlCommand()) 
{ 
    using(var con = new SqlConnection(ConnectionString)) 
    { 
     con.Open(); 
     cmd.Connection = con; 
     cmd.CommandText = "selectMusician"; 
     cmd.CommandType = CommandType.StoredProcedure; 
     cmd.Parameters.AddWithValue("@id", recordId); 
     ... 
    } 
} 

當時正好在MSDN上閱讀時,它說:「在完成使用Component時調用Dispose。Dispose方法使組件處於不可用狀態。調用Dispose之後,必須釋放對組件的所有引用,以便垃圾收集器可以回收組件佔用的內存。「這意味着爲了讓GC立即收集連接,必須在處理命令之前處理連接,否則連接會掛起,直到GC開始調用Finalize爲止

+0

但是這不正是Using語句所做的嗎?他們應該爲你處置。有人說明確地調用Dispose,即使你在你的連接中使用Using語句嗎?只是希望得到一個明確的答案。 – Kershaw

+0

是的,using語句調用Dispose。我上面的要點是讓它們按正確的順序排列,以便當連接的using語句處理連接時,命令(對連接有引用)在後面處理。這樣GC將立即收集連接,而不是等到它調用Finalize(可能需要一段時間)。 – Kevin

+0

有趣...關於嵌套使用語句的順序... – Kershaw

0

重構您的方法如下所示:您很可能會遇到數據讀取器引用連接並且尚未引發連接的情況

public Musician GetMusician(int recordId) 
{ 
    Musician objMusician = null; 

    using(SqlConnection con = new SqlConnection(_connectionString)) 
    { 
     con.Open(); 
     using (SqlCommand cmd = new SqlCommand()) 
     { 
      cmd.Connection = con; 
      cmd.CommandText = "selectMusician"; 
      cmd.CommandType = CommandType.StoredProcedure; 
      cmd.Parameters.AddWithValue("@id", recordId); 

      using (SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection)) 
      { 
       if (reader.HasRows) 
       { 
        reader.Read(); 
        objMusician = new Musician((int) reader["id"]); 
        objMusician.Name = (string) reader["name"]; 
       } 

       if objMusician != null) 
       { 
        objMusician.Albums = Albums.GetAlbums((int)objMusician.ID); 
        objMusician.Tours = Tours.GetTours((int)objMusician.ID); 
        objMusician.Interviews = Interviews.GetInterviews((int)objMusician.ID); 
       } 
      } 
     } 

     return objMusician; 
    } 
} 
+0

我認爲這是我見過的最好的結構,使用語句進行連接,然後命令,然後讀取器,並且沒有顯式的處理或關閉。 ExecuteReader上的CommandBehavior.CloseConnection是做什麼的?爲什麼有必要?如果好的做法,我會使用它,但以前沒有見過。 – Kershaw

+0

它確保您在完成讀取器後立即關閉連接(即關閉連接/處理完畢)。看到這裏:https://msdn.microsoft.com/en-us/library/system.data.commandbehavior(v=vs.110).aspx –

+0

看看我最近在其他項目中的代碼,我一直在使用與上面相同的結構,但沒有ExecuteReader上的CommandBehavior.CloseConnection。我想我會用它更新我的結構,但是,作爲一個新的改進... – Kershaw