2011-09-06 49 views
4

我目前正在創建一個WCF Web服務。SqlConnection/SqlCommand線程安全嗎?

作爲其工作的一部分,它不幸需要做一些相當密集的計算,但是這些計算可能會在調用web服務之間共享。實際上 - 我們只需要進行一次計算,所有後來的調用都可以獲得好處。

但是,由於WCF沒有共享應用程序狀態,因此將WCF設置爲單實例模式似乎是合理的。 (每個客戶端需要某些計算在所有的情形產生,迫使我們重新計算他​​們每serssion這可能是好的,或者每個調用,它是站不住腳的)

不過,我不是很熟悉的固定碼爲多個線程。 我一直在讀它,並且因爲我們的WCF代碼都沒有寫入共享狀態(除了易於保護的計算位),我幾乎相信我不需要改變任何東西。

雖然存在一個問題 - 我們使用SqlConnection和SqlCommand與我們的後端進行通信,我不確定是否可以指望這些線程安全?

編輯:我應該澄清一下,命令/連接總是本地的方法。我們在靜脈說話的模式:

using sqlConn = new SqlConnection(...) { 
try { 
    sqlConn.Open() 
} catch() { 
    throw new FaultException(); 
} 
var cmd = new SqlCommand("Some SQL", sqlConn); 
var reader = cmd.ExecuteReader(); 
//Read the stuff 
reader.Close(); 
//Return something 
} 

編輯完

我擡頭一看MSDN上的SqlCommand類: http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.aspx 它說:「任何公共靜態成員(在Visual Basic中的Shared)這種類型是線程安全的,任何實例成員都不能保證線程安全。「

我是否認爲這是正確解釋這意味着MS確實而不是保證SqlCommand在多線程場景中工作?

如果沒有,是否有線程安全的替代方案?

是的,我可以只鎖定在我的web服務所有的數據庫訪問方法,但一)它的醜陋和b)如果它沒有必要我寧願我沒得:)

乾杯提前!

+0

如果您不跨線程共享同一實例,並且類的靜態部分是線程安全的,那麼您沒有問題 –

+1

不要在線程之間共享這些實例,打開它們,運行查詢並處理儘快地。連接池將處理連接優化。 – TheCodeKing

回答

8

我是否認爲這是正確解釋這意味着MS不保證SqlCommand在多線程場景中工作?

只要正確使用它,它在多線程場景中工作正常。

如果有幾個線程試圖使用SqlCommand,你認爲會發生什麼?它怎麼可能工作?

但是如果不同的線程使用不同的連接向同一個數據庫發出不同的命令,那就沒有問題了。

有關MSDN上線程安全性的注意事項真的很糟糕,措辭也很糟糕,必須由不知道線程安全性的人寫的。他們試圖用這個消息說的東西(它被添加到MSDN上記錄的99.9%的類和函數中)是:「這種類型的任何靜態方法都可以安全地由多個線程同時調用。成員在同一實例不保證安全,如果多線程同時調用,但訪問同一成員不同對象是完全正常的。「

+0

同意 - 使用SAME SqlCommand的幾個線程將永遠不會工作。 我不確定的是,如果可以安全地擁有,就像你所說的,「不同的線程使用不同的連接向同一個數據庫發出不同的命令」。基本上,我怎麼會知道SqlCommand沒有一些瘋狂的內部靜態狀態,這將是一個問題?即使在我寫這篇文章時,我意識到這聽起來有多愚蠢,但是......所以,謝謝你的回答!我的代碼應該可以:-) – Fafnr

2

我不是100%確定你想要與SqlCommand同時做什麼,但無論內部線程安全,你肯定都會遇到問題,純粹是因爲使用SqlCommand需要它保持狀態,

SqlCommand cmd = myConnection.CreateCommand(); 
cmd.CommandText = "......"; 
cmd.Parameters.Add(.....); 
cmd.ExecuteNonQuery(); 

如果你想通過多個線程共享相同的命令,你必須在你用它來鎖定一些東西。

就SqlConnection而言,它只允許您一次打開一個查詢,因此如果您使用的是DataReaders,則需要再次鎖定某些內容。如果你想在同一時間運行多個事物,使用多個連接/命令是很重要的。

當你說WCF沒有共享應用程序狀態時,我也不確定你的意思 - 這不一定是真實的,它將取決於你如何託管你的WCF應用程序。如果它是一個WCF服務託管在IIS與aspNetCompatibilityEnabled="true"設置,您仍然有應用程序對象,您將在Web站點中。如果您還沒有使用aspNetCompatibility,還有其他選項。

+0

我意識到我很不清楚,所以我只是更新了一個我正在嘗試做的事情的例子......我不在方法調用之間共享命令/連接。我總是在每種方法中新增命令/連接。我不確定的是,如果他們內部有一些結構會咬我的屁股。 雖然我不知道有關aspNetCompatibilityEnabled - 謝謝!我很不確定這種結構的巧妙方式,有時候它確實可以幫助你將這些東西扔給那些一直在做這些東西的人:-) – Fafnr

2

只使用來自knly一個線程的連接和命令,而不關心那些應用程序級別的線程問題。 SQL服務器足以處理併發性,無需鎖定代碼。 .Net連接池也可以快速檢索有效的連接。

我並不是說你製作的整個WCF層不應該關心線程,但是它的DAL必須依靠db鎖而不是.net鎖來工作。