通过 SMO 获取链接服务器数据库表和视图

本文关键字:视图 数据库 服务器 SMO 获取 链接 通过 | 更新日期: 2024-11-08 06:12:58

如何通过SMO获取链接服务器上的SQL Server数据库?

Server server = GetServer("server");
Database db = server.Databases["db"];
LinkedServer ls = server.LinkedServers["ls"];

上面的第二行返回一个常规数据库。 第三行返回一个特定的链接服务器,该服务器提供对链接服务器连接的访问,但不提供对其数据的访问。 我怎样才能得到这样的东西:

Database db1 = server.LinkedServers["ls"].Databases["db"];

? 我需要这样做的原因是我将循环访问链接数据库中的不同对象,例如表或视图。

更新

为了进一步澄清,我目前有以下代码:

public void GenerateViews(string objectName = null)
{
    Server server = new Server("server");
    //Database a = server.Databases["a"];
    Database b = server.Databases["b"];
    b.Tables.OfType<Table>().ToList().ForEach(o => ProcessSqlObject(o));
    b.Views.OfType<View>().ToList().ForEach(o => ProcessSqlObject(o));
}
//takes all tables and views in database b that have a custom extended property "CreateView", and create a view for it in database a
private void ProcessSqlObject(dynamic o)    //o MUST be an SMO table or view (since they don't implement a common interface, I'm using a dynamic)
{
    Database ct = (Database)o.Parent;
    Database a = ct.Parent.Databases["a"];
    const string viewPrefix = "V_CTC_";   
    const string SourceIDColumnName = "SourceID";    
    string objectName = (string)o.Name;   //name of table or view
    objectName = objectName.StartsWith("V_", StringComparison.InvariantCultureIgnoreCase) ? objectName.Substring(2) : objectName;
    string viewName = viewPrefix + objectName;  //remove V_ from view, so that we don't have "V_V_".
    ExtendedProperty ep = (ExtendedProperty)o.ExtendedProperties["CreateView"];
    bool AlreadyExists = a.Views.OfType<View>().Any(v => v.Name == viewName);
    if (ep != null && ep.Value.ToString() == "1")  //there IS an extended property, and its value is 1, meaning, we want a view
    {
        if (!AlreadyExists) //we don't already have the view    
        {
            //ProcessSqlObject(t, viewName, SourceIDColumnName, ct, a);
            StringBuilder ws = new StringBuilder();
            ws.AppendLine("SELECT");
            ws.AppendLine("'t2 [" + SourceIDColumnName + "]");
            ((ColumnCollection)o.Columns).OfType<Column>().ToList().ForEach(c =>
            {
                ws.AppendLine("'t, [" + c.Name + "]");
            });
            string linkedServer = "[ls].";
            ws.AppendLine("FROM " + linkedServer + "[" + ct.Name + "].[dbo].[" + o.Name + "] WITH(NOLOCK)");
            string rt = ws.ToString();
            rt = rt.Replace("wholesale", "retail");
            rt = rt.Replace("2 [" + SourceIDColumnName + "]", "3 [" + SourceIDColumnName + "]");
            StringBuilder sql = new StringBuilder();
            sql.AppendLine("CREATE VIEW " + viewName + " AS");
            sql.AppendLine();
            sql.AppendLine(ws.ToString());
            //sql.AppendLine();
            sql.AppendLine("UNION ALL");
            sql.AppendLine();
            sql.AppendLine(rt);
            Console.WriteLine(sql);
            a.ExecuteNonQuery(sql.ToString());
        }
    }
    else    //we DON't want the view
    {
        a.Views.OfType<View>().Single(v => v.Name == viewName).Drop();
        a.Refresh();
        }
    }
}

我目前正在将给定数据库中的所有表和视图传递给第二个函数。 这是没有使用链接服务器的。 我希望能够做同样的事情,但对于链接服务器,而不必重写代码。

谢谢。

通过 SMO 获取链接服务器数据库表和视图

您无需连接到服务器即可获取表和视图(如果您只需要它们的名称)。类为此提供了 EnumTables 方法。

LinkedServer 类具有一个数据源属性,您应该能够将其用作远程服务器的名称。如果将其传递给 GetServer() 函数,则应返回 SMO 服务器对象。