获取包含表的数据库列表的有效方法

本文关键字:有效 方法 列表 数据库 包含表 获取 | 更新日期: 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个线程并不是那么多……实验和配置文件,但这是我通常采用的方法。