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

C# 通过SMO获取链接的服务器数据库表和视图,c#,sql-server,linked-server,smo,C#,Sql Server,Linked Server,Smo,如何通过SMO获取链接服务器上的SQL Server数据库 Server server = GetServer("server"); Database db = server.Databases["db"]; LinkedServer ls = server.LinkedServers["ls"]; 上面的第二行返回一个常规数据库。第三行返回一个特定的链接服务器,它提供对链接服务器连接的访问,但不提供对其数据的访问。我怎样才能得到这样的东西: Database db1 = server.Lin

如何通过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();

        }
    }
}
public void GenerateViews(string objectName=null)
{
服务器=新服务器(“服务器”);
//数据库a=服务器。数据库[“a”];
数据库b=服务器。数据库[“b”];
b、 ToList().ForEach(o=>ProcessSqlObject(o));
b、 Views.OfType().ToList().ForEach(o=>ProcessSqlObject(o));
}
//获取数据库b中具有自定义扩展属性“CreateView”的所有表和视图,并在数据库a中为其创建视图
private void ProcessSqlObject(dynamic o)//o必须是SMO表或视图(因为它们没有实现公共接口,所以我使用的是dynamic)
{
数据库ct=(数据库)o.Parent;
数据库a=ct.Parent.Databases[“a”];
const string viewPrefix=“V_CTC_”;
常量字符串SourceIDColumnName=“SourceID”;
string objectName=(string)o.Name;//表或视图的名称
objectName=objectName.StartsWith(“V_908;”,StringComparison.InvariantCultureInogoreCase)?objectName.Substring(2):objectName;
字符串viewName=viewPrefix+objectName;//从视图中删除V_u,这样我们就不会有“V_V_u”。
ExtendedProperty ep=(ExtendedProperty)o.ExtendedProperties[“CreateView”];
bool AlreadyExists=a.Views.OfType().Any(v=>v.Name==viewName);
如果(ep!=null&&ep.Value.ToString()=“1”)//有一个扩展属性,其值为1,这意味着我们需要一个视图
{
如果(!AlreadyExists)//我们还没有视图
{
//ProcessSqlObject(t、viewName、SourceIDColumnName、ct、a);
StringBuilder ws=新的StringBuilder();
ws.AppendLine(“选择”);
ws.AppendLine(“\t2[”+SourceIDColumnName+“]”);
((ColumnCollection)o.Columns).OfType().ToList().ForEach(c=>
{
ws.AppendLine(“\t,[“+c.Name+”]);
});
字符串linkedServer=“[ls]”;
ws.AppendLine(“FROM”+linkedServer+“[”+ct.Name+“][dbo]。“+o.Name+”]WITH(NOLOCK)”;
字符串rt=ws.ToString();
rt=rt.替换(“批发”、“零售”);
rt=rt.Replace(“2[“+SourceIDColumnName+”],“3[“+SourceIDColumnName+”]”);
StringBuilder sql=新的StringBuilder();
AppendLine(“创建视图”+viewName+“作为”);
AppendLine();
AppendLine(ws.ToString());
//AppendLine();
sql.AppendLine(“联合所有”);
AppendLine();
sql.AppendLine(rt);
Console.WriteLine(sql);
a、 ExecuteNonQuery(sql.ToString());
}
}
否则//我们不想要这个视图
{
a、 Views.OfType().Single(v=>v.Name==viewName.Drop();
a、 刷新();
}
}
}
我目前正在将给定数据库中的所有表和视图传递给第二个函数。这不需要使用链接服务器。我希望能够做同样的事情,但对于一个链接服务器,而不必重写代码


谢谢

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

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

我已经有了一个方法,可以在非链接服务器数据库的表中循环,我希望将此传递给该方法,而不必重写所有内容。还有其他方法吗?你能用你的方法签名更新问题吗?它对表/视图有什么作用?对,所以您正在编写数据库脚本。。。如果我们找到了将它们放在您期望的相同对象中的方法,请使用se…很好的解决方法!但是,假设链接服务器的IP或端口关闭,因此无法直接访问,但可以通过主服务器访问(假设它们都在同一台物理机器上),在这种情况下,这将不起作用。类似地,在我的例子中,链接服务器位于不同的LAN上,它的公共名称与内部名称不同:(它应该返回您在创建链接服务器时输入的任何名称。这里没有魔法。如果您从不同的网络访问链接服务器指向的服务器,这是另一个问题,但此解决方案解决了您提出的问题。