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

时间:2011-08-15 23:06:42

标签: c# sql sql-server sql-server-2005

我需要将两个带有附加数据库列表的下拉框填充到包含特定命名表的服务器。我目前的方法就是这个。

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();
            });
    }

}

1 个答案:

答案 0 :(得分:4)

我会在一个单独的线程中运行每一个,然后在继续之前将它们全部加入。当然,您需要使用线程安全结构来执行此操作,但这样可以让您同时发送所有请求,这样您就不必等待每个请求转移到下一个请求。

如果你有200个数据库,你可能想要为每个使用一个线程池而不是一个线程,但是再次,200个线程不是那么多......实验和配置文件,但这是我将采取的一般方法