2012-03-07 37 views
4

我正在使用SMO從Sql服務器數據庫使用.Net代碼編寫腳本。但截至目前,我正在經歷一個循環。使用SMO編寫並行循環中的.net中SQL服務器數據庫的對象定義

foreach(var table in TableCollection) 
{ 
var stringCollection=table.Script(); 
} 

它工作正常。但是,當我將其轉化循環爲Parallel.ForEach循環,如:

Parallel.ForEach(TableCollection,table=> 
{ 
var stringCollection=table.Script(); 
}); 

它沒有腳本。有沒有人使用相同的方法或其他方法來並行編寫Sql服務器中的對象?

UPDATE:

我一直沒能制定出並行循環到現在爲止,但我下面提到的代碼中使用:

server.SetDefaultInitFields(true);     

它改善了性能上有一定影響。

+0

它究竟如何失敗?它會拋出一些異常嗎? – svick 2012-03-07 08:57:03

+0

是的,它拋出一個異常,就是已經有一個與此命令關聯的OPEN數據讀取器。可能是兩個線程並行嘗試編寫SERVER對象(使用同一個實例)時會造成麻煩。 – AjayK 2012-03-07 09:18:52

回答

4

看來SMO不是以線程安全的方式構建的。當您在Table上調用Script()時,它將使用Server中的某個共享狀態,因此無法在同一個Server的兩個表上執行它。但是你可以解決,通過爲每個Table創建新Server對象:

private static TableCollection GetTables() 
{ 
    Server server = new Server(…); 
    Database database = server.Databases[…]; 
    var tables = database.Tables; 
    return tables; 
} 

… 

Parallel.For(0, GetTables().Count, 
    i => 
    { 
     var stringCollection = GetTables()[i].Script(); 
     … 
    }); 

這會讓你的並行查詢,但我不知道是否會讓他們真正更快。

編輯:如果你想爲每個線程創建一個Server,你可以使用的Parallel.For()過載,使線程本地初始化。喜歡的東西:

Parallel.For(0, GetTables().Count, 
    () => GetTables(), 
    (i, _, tables) => 
    { 
     var stringCollection = tables[i].Script(); 
     … 
     return tables; 
    }, 
    tables => { }); 

這樣,每個線程都有自己的Server對象,但只有一個。

+0

其實這種方式我知道它會工作..但事情是我有表,SP和所有其他可能的對象,所以這種方法似乎是非常昂貴的,尤其是當沒有。的物體以千分之十的速度運行。 – AjayK 2012-03-07 16:40:32

+1

在這種情況下,您可以確保每個線程都有一個「服務器」。 – svick 2012-03-07 16:46:54

+0

但我不是很確定,如何訪問並行循環中的線程,以便我可以確保每個線程只有一個服務器對象。或者你正指着我們自己創建線程。 – AjayK 2012-03-07 19:35:42

相關問題