2015-03-09 3 views
0

Как получить базы данных SQL Server, которые находятся на связанном сервере через SMO?Получение привязанных таблиц и представлений базы данных сервера через SMO

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

Вторая строка выше возвращает обычную базу данных. Третья строка возвращает определенный связанный сервер, который обеспечивает доступ к соединенному серверному соединению, но не к его данным. Как я могу получить что-то вроде:

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

? Причина, по которой мне это нужно, это то, что я буду перебирать разные объекты в связанной базе данных, такие как таблицы или представления.

UPDATE

Для дальнейшего уточнения, я в настоящее время этот код:

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

     } 
    } 
} 

я в настоящее время проходящий второй функции все таблицы и представления в данной базе данных. Это без использования связанного сервера. Я хочу иметь возможность делать то же самое, но для связанного сервера, не переписывая код.

Спасибо.

ответ

1

Вам не нужно подключаться к серверу, чтобы получить таблицы и представления (если вам просто нужны их имена). Класс LinkedServer предоставляет для этого EnumTables method.

+0

У меня уже есть метод, который проходит через таблицы для не связанных с сервером db, и я хочу передать это этому методу, не переписывая все. Есть ли другой путь? – as9876

+0

Можете ли вы обновить вопрос своей сигнатурой метода? И что он делает с таблицами/представлениями? – Juan

+0

Я обновил его, ty. – as9876

1

LinkedServer class имеет свойство DataSource, которое вы должны использовать в качестве имени удаленного сервера. Если вы передадите это на свою GetServer() функцию, вы должны вернуть объект SMO Server.

+0

Хороший обходной путь! Однако предположим, что IP или порт связанного сервера были недоступны, поэтому к нему нельзя было получить доступ напрямую, но к нему можно было получить доступ через главный сервер (предположим, что они оба находятся на одной физической машине), в этом сценарии это не будет Не работай. – as9876

+0

Аналогично, в моем случае связанный сервер находится в другой локальной сети, а его общедоступное имя отличается от его внутреннего :( – as9876

+0

Он должен возвращать любое имя, которое вы ввели при создании связанного сервера. Здесь нет никакой магии. «Доступ к серверу, на который указывает связанный сервер из другой сети, - это еще одна проблема, но это решение решает поставленный вами вопрос. –

Смежные вопросы