获取包含表的数据库列表的有效方法
本文关键字:有效 方法 列表 数据库 包含表 获取 | 更新日期: 2023-09-27 18:05:35
我需要用附加到服务器的数据库列表填充两个下拉框,其中包含一个特定命名的表。我现在的方法是这样的。
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,做更多的客户端处理,或者在服务器上运行它作为某种形式的复杂查询。只要根据两个表名得到两个列表,就满足了我的需求。这是更新的版本,使我的运行时间下降到不到一秒,感谢total的建议。
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();
});
}
}
我会在一个单独的线程中运行每个线程,然后在继续之前将它们全部连接起来。当然,你需要使用线程安全的结构来做到这一点,但这将允许你同时发送所有的请求,这样你就不必等待每个请求移动到下一个请求。
如果你有200多个数据库,你可能想使用一个线程池而不是一个线程,但话又说回来,200个线程并不是那么多……实验和配置文件,但这是我通常采用的方法。