2011-08-15 85 views
2

我需要將包含特定命名錶的服務器的附加數據庫列表填充到兩個下拉框中。我目前的方法是這樣的。獲取包含表的數據庫列表的有效方法

List<string> dbType1 = new List<string>(); 
List<string> dbType2 = new List<string>(); 
using (var conn = new SqlConnection("Data Source=(local);Integrated Security=true")) 
using (var cmd = new SqlCommand()) 
{ 
    conn.Open(); 
    cmd.Connection = conn; 

    cmd.CommandText = "select name from sys.databases"; 
    using (var innerConn = new SqlConnection("Data Source=(local);Integrated Security=true")) 
    using (var innerCmd = new SqlCommand()) 
    using (var rdr = cmd.ExecuteReader()) 
    { 
     innerConn.Open(); 
     innerCmd.Connection = innerConn; 

     while (rdr.Read()) 
     { 
      string table = rdr.GetString(0); 
      innerCmd.CommandText = String.Format("select name from [{0}]..sys.tables where name in 'EF_LAB_FIELDS_DYNA' 'AUTOXPAY_PAYMENTS'", table); 

      object result = innerCmd.ExecuteScalar(); 

      if(result != null) 
      { 
       if ((string)result == "EF_LAB_FIELDS_DYNA") 
        dbType1.Add(table); 
       else 
        dbType2.Add(table); 
      } 
     } 

    } 

} 

cb.Items.AddRange(dbType1.ToArray()); 
cb2.Items.AddRange(dbType2.ToArray()); 

這可以工作,但是在具有205個附加數據庫的服務器上運行需要44.6秒。

任何人都可以給我任何關於如何加快此操作的建議嗎?我願意使用SMO等其他技術,進行更多的客戶端處理,或者將其作爲服務器上某種形式的複雜查詢運行。只要我根據兩個表名得到兩個列表,它就能滿足我的需求。


下面是更新後的版本,使我的運行時間降到了第二位,這要歸功於總的建議。

ConcurrentBag<string> dbType1 = new ConcurrentBag<string>(); 
ConcurrentBag<string> dbType2 = new ConcurrentBag<string>(); 
List<string> databases = new List<string>(); 
using (var conn = new SqlConnection("Data Source=(local);Integrated Security=true")) 
using (var cmd = new SqlCommand()) 
{ 
    conn.Open(); 
    cmd.Connection = conn; 

    cmd.CommandText = "select name from sys.databases"; 

    using (var rdr = cmd.ExecuteReader()) 
    { 
     while (rdr.Read()) 
     { 
      databases.Add(rdr.GetString(0)); 
     } 

     Parallel.ForEach(databases,() => 
      { 
       var innerConn = new SqlConnection("Data Source=(local);Integrated Security=true"); 
       var innerCmd = new SqlCommand("", innerConn); 
       innerConn.Open(); 
       return innerCmd; 
      }, 
      (database, loopState, localCommand) => 
      { 
       localCommand.CommandText = String.Format("select name from [{0}].sys.tables where name in ('EF_LAB_FIELDS_DYNA', 'AUTOXPAY_PAYMENTS')", database); 

       object result = localCommand.ExecuteScalar(); 

       if (result != null) 
       { 
        if ((string)result == "EF_LAB_FIELDS_DYNA") 
         dbType1.Add(database); 
        else 
         dbType2.Add(database); 
       } 

       return localCommand; 
      }, 
      (localCommand) => 
      { 
       var temp = localCommand.Connection; 
       localCommand.Dispose(); 
       temp.Dispose(); 
      }); 
    } 

} 
+0

你有什麼可以分析,看看時間正在接受?我的猜測主要是打開你可能無法避免的連接。 – pstanton

+0

@pstanton我只打開兩個連接並重新使用它們,如果表存在,則花費在查詢上的時間。 –

回答

4

我會在一個單獨的線程中運行每個線程,然後在繼續之前加入它們。當然,您需要使用線程安全結構來執行此操作,但這樣可以讓您同時發送所有請求,因此您不必等待每個請求都轉到下一個請求。

如果你有200個數據庫,你可能想要爲每個線程使用一個線程池而不是一個線程,但是200線程不是那麼多......實驗和配置文件,但這是我的一般方法採取。

+0

也會確保在它們之間共享它們之間的連接 –

+0

將該查詢放在'Parallel.ForEach'中會使我的運行時間縮短到0.8秒。 –

+0

非常好。我不是一個C#人,所以我不能給你具體的東西。很高興通用的解決方案可以應用您對圖書館的瞭解,以獲得成功! .8比44好多了! :-D – corsiKa

相關問題