Использование веб-сервисов для работы с удаленными SQL серверами (исходники)

Tomas Shestakov aka Megaprog

В данной статье рассматриваются проблемы, возникающие при работе с SQL серверами, находящимися в сети Интернет, а также пути их разрешения при помощи веб сервисов. В качестве примера приводится организация работы с MS SQL Server 2000 посредством использования веб службы WebDBConnector, разработанной автором этой статьи, скомпилированный код которой доступен на сайте www.megaprog.4u.ru.

Итак, допустим, мы разрабатываем веб-приложение. У нас есть ASP.Net хостинг, на котором присутсвует SQL база данных, сервер, в принципе, значения не имеет (хотя статье упор делается на MS SQL Server). Провайдер разрешает нам доступ к SQL серверу через сокет (некий IP и порт), и все дальнейшие проблемы целеком ложаться на наши плечи. Либо, ситуация вторая, наше предприятие очень велико, имеет множество территориально удаленных филиалов, связь только через Internet, а работать с центральной базой как-то надо. В обоих случаях перед нами возникают сходные проблемы:

  1. Безопасность. Если доступ к SQL серверу осуществляется напрямую через IP, возникает брешь в безопасности как на стороне клиента, так и на сервере. Причем клиент может быть отгорожен фаерволом или прокси, что вообще делает невозможным прямой доступ к SQL серверу.
  2. Надежность. Зачастую связь через Интернет является нестабильной, возможны обрывы связи. Если программа, работающая с SQL использует постоянное или длительное соединение с сервером это будет приводить к частым ошибкам и сделает невозможным стабильную работу такой программы. Весь стандартный инструментарий MS SQL Server работает именно таким образом - соединение с базой данных поддерживается постоянно.
  3. Скорость. Стандартные протоколы обмена данными между SQL сервером и клиентом, как правило, не расчитаны для работы в интернет. Передается множетсво избыточной информации и т.д. В результате время между запросом и получением результирующего набора данных может стать очень большим. Возможны частые таймауты, т.е. программа будет считать, что сервер не отвечает, в то время как информация просто поступает с очень большой задержкой.

Для решения этих и многих других проблем при работе с удаленными SQL серверами логично будет использовать програмное обеспечение промежуточного (в данном случае 3-го) уровня. Выбор архитекур и средств разработки очень велик. Мы же рассмотрим использование самой перспективной в настоящий момент технологии - веб сервисов. Для примера возьмем веб службу WebDBConnector, она развернута в Интернет по адресу: www.megaprog.4u.ru/webdbconnector.asmx, сайт разработчика, соотвественно, www.megapprog.4u.ru.

Теперь рассмотрим методы WebDBConnector'а, для простоты используя синтаксис C#:

bool CheckConnection(string connstr)
Проверяет возможность соединения с базой данных, т.е. осуществляется коннект и в случае успеха 
возвращается true, иначе неудаче false
connstr - строка соединения какую мы передаем .Net OleDb провайдеру

bool CheckConnectionEx(string connstr, out SqlErrorInfo e)
Выполняет такое же действие, как предыдущий метод, только сразу возвращает 
e - класс, содержащий информацию об ошибке, который мы рассмотрим позже

QueryResult ExecQuery(string query)
Выполняет запрос к базе данных используя строку соединения, переданную предыдущим вызовом 
CheckConnection или ExecQueryEx. Возвращает класс QueryResult, содержащий всю информацию о 
результате выполнения запроса
query - строка запроса

QueryResult ExecQueryEx(string query, string connstr)
Тоже действие, как предыдущий метод, но строка передается явно 
connstr	- строка соединения

string GetConnectionString()
Возвращает строку соединения, переданную предыдущим вызовом CheckConnection или ExecQueryEx

string GetLastQuery()
Возвращает строку предыдущего запроса, выполненного методом ExecQuery или ExecQueryEx

SqlErrorInfo GetLastError()
Возвращает информацию о последней ошибке, возникшей при обращении к SQL серверу 

Кратко о служебных классах:

public class QueryResult { //Информация о результате выполнения запроса
    
    //Был ли получен в результате запроса набора значений
    public bool IsResultset;
    
    //Значение первого столбца первой строки результата
    public object Scalar;
    
    //Количество обработанных (возвращенных) записей
    public int RecordsProcessed;
    
    //Набор записей полученных в результате запроса
    public System.Data.DataSet Resultset;
    
    //Информация об ошибке, возникшей при выполнении запроса
    public SqlErrorInfo Error;
}

public class SqlErrorInfo { //Bнформация об ошибке, возникшей при обращении к SQL серверу
    
    //Ошибка SQL сервера или некая другая	(было ли OleDbException)
    public bool IsSqlError;
    
    //Сообщение об ошибке
    public string Message;
    
    //Источник возникновения ошибки
    public string Source;
    
    //HRESULT ошибки	(если	IsSqlError)
    public int ErrorCode;
    
    //специфичная базе данных информация об ошибке
    public int NativeError;
    
    //пятисимвольное значение, соответствующее ANSI SQL стандарту
    public string SQLState;
    
    //описание ошибки, возвращаемое ToString()
    public string Description;
}

Как мы видим, набор методов WebDBConnector'а не велик и синтаксис их совсем не сложен. Тем не менее эта веб служба позволяет осуществлять работу с удаленной SQL базой достаточно эффективно. Следует учесть, что все методы службы используют переменные состояния сессии (Session state), поэтому перед вызовом любого метода обязательно должно быть проиннициализированно свойство прокси класса CookieContainer.

Для иллюстрации простоты использования WebDBConnector'а создадим простое Windows приложение, которое будет выполнять запросы к базе данных и выводить их результаты на экран. В качестве средства разработки будем использовать VS.Net, в качестве языка программирования C#. Чтобы не загромождать код, будем считить, что вызовы методов веб службы всегда успешны, и не будем делать обработчики исключений на этот случай.

Для того, чтобы пример полностью заработал необходимо либо иметь хостинг на a href="http://hosting.gotdotnet.ru/" target="_blank">hosting.gotdotnet.ru, либо разместить WebDBConnector на другом хосте (можно прямо на своей машине) и в дальнейшем ссылаться на свой адрес WebDBConnector'а.

  1. Создаем новый проект - Windows Application с именем QueryTest.
  2. Для созданного проекта выбираем Add Web Reference, задаем адрес www.megaprog.4u.ru/webdbconnector.asmx (или другой адресс где находится веб служба WebDBConnector), жмем кнопку Go. После инициализации станет доступна кнопка Add Reference. Жмем ее, система создаст покси класс, потомок System.Web.Services.Protocols.SoapHttpClientProtocol класса, который делает работу с веб службой очень удобной. Следует учесть, что прокси класс будет иметь собственно пространство имен - <имя приложения>.<веб сервер> В нашем случае это будет QueryTest.ru.gotdotnet.hosting
  3. Размещаем на фомре следующие элементы управления:
    • TextBox (желательно вверху) - очищаем свойство Text;
    • Button (справа от TextBox'а) - меняем Text на Run; DataGrid (на всем оставшемся пространстве формы) - свойство ReadOnly в true.
  4. Нажимаем кнопку View Code для формы, к классу формы добавляем слудующие поля:

    private System.Net.CookieContainer Cookies=new System.Net.CookieContainer();
    private ru.gotdotnet.hosting.WebDBConnector DBConnector=new ru.gotdotnet.hosting.WebDBConnector();
    private ru.gotdotnet.hosting.QueryResult QResult;
    private string ConnectionString="Provider=SQLOLEDB.1;Data Source=DOTNET\\HOSTING;" +
        "Persist Security Info=True;User ID=User;Password=Password;Initial Catalog=H_User";
    
    разумеется значение поля ConnectionString вы должны исправить соответственно вашей базе данных. Значения Data Source, User ID, Password, Initial Catalog вымышлены, я не могу открыть настоящий пароль своей базы.

  5. Переключаемся на View Designer формы, два раза щелкаем на форме. Дизайнер генерит обработчик события формы Load, здесь поместим сначала код инициализации Cookie контейнера нашего прокси-класса:

    DBConnector.CookieContainer=Cookies;
    

  6. Сюда же добавим код, проверяющий возможность соединения с базой данных и в случае неуспеха выдающий сообщение об ошибке:

    if (! DBConnector.CheckConnection(ConnectionString)) {
    	MessageBox.Show(DBConnector.GetLastError().Description,"Произошла ошибка!");
    	Application.Exit();
    }
    

  7. Снова переключаемся на окно дизайнера формы и делаем двойной клик на кнопочке "Run". Пишем код отправляющий запрос на выполнение и выводящий результат на экран:

    QResult=DBConnector.ExecQuery(textBox1.Text);
    if (QResult.IsResultset) { 
    	dataGrid1.SetDataBinding(QResult.Resultset,QResult.Resultset.Tables[0].TableName);
    }
    else {
    	if (QResult.Error != null) 
    		MessageBox.Show(QResult.Error.Message,"Ошибка в запросе!");
    	else
    		MessageBox.Show(QResult.RecordsProcessed + " записей обработано",
    			"Записей возвращено не было");
    	dataGrid1.SetDataBinding(null,"");
    }
    

Вот, собственно и все. Запускаем нашу программу, вводим запрос, жмем Run и получаем либо набор записей на экране, либо сообщение о количестве обработанных записей, либо сообщение об ошибке. Как мы видим, количество кода, требуемое для работы с веб службой WebDBConnector минимально, удобство в работе налицо.

Итог:

Использование веб сервисов для работы с удаленными базами данных позволяет решить большинство известных проблем и не приведет к существенному усложнению кода. Прекрасным примером подобного веб сервиса является WebDBConnector, создателем которого является автор статьи.


Страница сайта http://test.interface.ru
Оригинал находится по адресу http://test.interface.ru/home.asp?artId=4926