SQL.RU
 client/server technologies
Rambler's Top100
 Главная | Документация | Статьи | Книги | Форум | Опросы | Каталог | Гостевая | Рассылка | Работа | Поиск | FAQ |
XML в MS SQL Server 2000 и технологиях доступа к данным | SQL Server как Web-сервис Дальше »

Web-сервис - это компонент, к которому можно обращаться с помощью XML. Результаты вызова метода также оборачиваются в XML. Протокол устройства XML-сообщений, которыми обмениваются клиент и Web-сервис, называется SOAP. В отличие от RPC и других бинарных, зависимых от платформы протоколов, ориентированных на плотное взаимодействие, SOAP предусматривает работу в слабосвязанных средах (Интернет) и, будучи основан на XML, позволяет общаться компонентам независимо от операционной системе или инструмента разработки, в которых они были созданы. Потребность в удаленном взаимодействии компонентов через Интернет назрела давно. В свое время HTML-формы и ASP превратили посетителя Web-узла из пассивного зрителя, просматривающего заранее подготовленные странички, в активного участника, формирующего страницу по информации из базы на основе своих критериев. Однако эта информация доставлялась потребителю по-прежнему в HTML-формате, что, может быть, удобно с точки зрения визуального восприятия, но никуда не годится, если вы хотите, например, выцепить из полученной странички котировки акций, превратить их в recordset и передать своему приложению. Web-сервисы публикуют описания своих интерфейсов в wsdl-файлах (аналог библиотеки типов в СОМ). Например, методу, возвращающему котировки, нужно подать на вход интересующую дату и биржевой символ. Чтобы найти подходящий Web-сервис или выяснить назначение найденного, можно использовать универсальный реестр UDDI и протокол DISCO. В Visual Studio.Net входят средства создания как самих Web-сервисов, так и клиентов, их использующих. Например, не составляет труда создать Web-сервис, который будет принимать имя и параметры хранимой процедуры на SQL Server, выполнять ее и отсылать результаты клиенту. Словом, типичная трехуровневая архитектура, только клиентская компонента, компонента бизнес-логика и сервер теперь не ограничены пределами локальной сети, а находятся где угодно в Интернете. Начиная с SQLXML 3.0 в роли Web-сервиса может выступать SQL Server 2000, так что надобность в промежуточной компоненте теперь отпадает. Присутствие ПО промежуточного слоя наиболее часто оправдывают требованиями безопасности, масштабируемости и программируемости. Последние два, вероятно, наиболее честные, потому что я с трудом понимаю, как толщина middleware может влиять на устойчивость сервера к попыткам несанкционированного проникновения. Если вы дыряво настроили политики безопасности на сервере, то злоумышленник все равно на него придет независимо от того, 5 шагов ему перед этим придется сделать или 10. Вот программируемость - это уже серьезней. Т-SQL до сих пор остается странной смесью мощи и ограничений. Отсутствие многих обыденных для современных языков конструкций, не говоря уже об ООП, приводило к тому, что народ утешал себя тем, что SQL не для того предназначался, и уходил писать логику на С++, Visual Basic, Delphi и т.д. В последнее время круг задач, решаемых SQL Server, очень сильно расширился за рамки пресловутого SQL, следовательно, возможности языка программирования на серверной стороне, как бы он ни назывался, должны им соответствовать. И они будут соответствовать в следующей версии. Пункт третий - масштабируемость. С целью повышения масштабируемости и распределения нагрузки в SQL Server 2000, как известно, были введены распределенные фрагментированные представления. Несмотря на то, что благодаря этому механизму SQL Server занимает в настоящий момент первые места в рейтингах производительности, следует понимать, что в действительности это лишь первый этап на пути к базе данных, автоматически распределяемой по многим серверам в сети, когда каждый узел, получивший запрос, разбивает его на подзапросы к тем серверам, где в действительности лежат нужные данные (а если они продублированы, то к наименее загруженным). Таким образом, понятно, что все три критерия обособления являются достаточно условными, и не всегда компоненты бизнес-логики будут выноситься за пределы SQL Server. Следовательно, тот факт, что клиентское приложение сможет общаться с ним напрямую как с Web-сервисом, на самом деле очень важен. Вернемся к Скрипту 14.
Для запросов к SQL Server по SOAP мы создаем еще один подкаталог websvc виртуальной директории и присваиваем ему тип vtSOAP. Его необходимо проассоциировать с физической поддиректорией (\WebService), т.к. в ней будет храниться wsdl и др. файлы, описывающие данный Web-сервис. Не мудрствуя лукаво, обзовем его SQLSoapSample. Методами могут выступать хранимые процедуры / функции, либо хранимые шаблоны. Первые добавляются как AddStoredProcMethod. Параметрами выступают имя метода, под которым он будет виден и вызываться с клиента, имя хранимой процедуры или функции, если в SELECT участвуют несколько таблиц, соединенных оператором JOIN, то должны ли они на клиенте получаться как вложенные элементы в случае XML-вывода / связанные таблицы в случае DataSet-вывода (1 - да, 0 - как независимые), должны ли ошибки выполнения возвращаться как ошибки SOAP (1 - да, 0 - нет) и что является результатом работы метода Web-сервиса: массив элементов XML, единственный DataSet или массив DataSet'ов. В данном случае выбран второй вариант. Массив DataSet'ов имеет смысл использовать в том случае, когда внутри процедуры выполняются несколько независимых SELECT'ов. Хранимая процедура CustomerOrdersForYear состоит из одного параметризованного запроса, с которым мы работали еще со Скрипта 3.


CREATE PROCEDURE CustomerOrdersForYear @Name nvarchar(20), @Year smallint AS
SELECT c.ContactName, c.ContactTitle, o.OrderDate, o.Freight FROM Customers c 
INNER JOIN Orders o ON c.CustomerID = o.CustomerID 
WHERE c.ContactName like @Name + '%'  and year(o.OrderDate) = @Year

Скрипт 19

В качестве второго метода Web-сервиса выбираем шаблон из п.10 (рис.6). Он добавляется вызовом AddTemplateMethod. Параметрами служат внешнее имя метода, местоположение шаблона относительно данного скрипта и способ передачи ошибок (SOAP - да/нет). Результат шаблона можно передавать только как набор XML-элементов. Строка sqlWebSvc.SoapMethods.GenerateWSDL(); производит автоматическую генерацию wsdl-файла, который кладется в физическую директорию, соответствующую виртуальному подкаталогу типа soap. После этого Web-сервис становится доступным для обращений. Как и в классическом DCOM, на машине клиента нужно создать прокси, содержащего сигнатуру методов Web-сервиса. В графической среде разработки Visual Studio это происходит автоматически при добавлении ссылки на wsdl-файл в раздел Web References проекта. Прокси можно также сгенерировать с помощью утилиты командной строки wsdl.exe:


wsdl.exe /l:CS /o:SQLSrvWebService_Proxy.cs /n:SQLSrvWebRef
http://localhost/SQLXML3/websvc?wsdl

В качестве параметров здесь передаются язык, на котором будет создан прокси, имя файла с прокси, его пространство имен и URI Web-сервиса с его описанием в виде wsdl. Обращение клиента к Web-сервису показано в Скрипте 20.


static void SQLSrvWebService_Client()
{
	SQLSrvWebRef.SQLSoapSample proxy = new SQLSrvWebRef.SQLSoapSample();
	proxy.Credentials = System.Net.CredentialCache.DefaultCredentials;
	
	Console.WriteLine("----------------------------------------------------------------");
	Console.WriteLine("Результаты выполнения шаблона (всегда как массив XML-элементов):");
	object[] resultXml = proxy.ПримерВызоваШаблона("20", "1000");
	foreach (XmlElement x in resultXml)
	Console.WriteLine(x.OuterXml);
		
	Console.WriteLine("\n----------------------------------------------------------------");
	Console.WriteLine("Результаты выполнения хранимой процедуры (заказаны как DataSet):");
	int retVal;
	DataSet resultRel = proxy.ЗаказыКлиентаЗаГод("Maria", 1997, out retVal);

	DataRelation rel = resultRel.Relations[0];
	Console.WriteLine("\nТаблицы связаны отношением " + rel.RelationName);
	Console.Write("Родительская таблица " + rel.ParentTable.TableName + ", родительский ключ - ");
	foreach (DataColumn c in rel.ParentColumns) Console.Write(c.ColumnName + " ");
	Console.Write("\nДочерняя таблица " + rel.ChildTable.TableName + ", дочерний ключ - ");
	foreach (DataColumn c in rel.ChildColumns) Console.Write(c.ColumnName + " ");
	Console.WriteLine("");

	foreach (DataRow rParent in rel.ParentTable.Rows)
	{
		Console.WriteLine("\nТаблица " + rel.ParentTable.TableName);
		foreach (DataColumn cParent in rel.ParentTable.Columns) Console.Write(cParent.Caption 
		+ ": " + rParent[cParent] + "; ");
		Console.Write("\n\tСвязанные записи из таблицы " + rel.ChildTable.TableName);
		foreach (DataRow rChild in rParent.GetChildRows(rel))
		{
			Console.Write("\n\t");
			foreach (DataColumn cChild in rel.ChildTable.Columns) 
			Console.Write(cChild.Caption + ": " + rChild[cChild] + "; ");
		}
		Console.WriteLine("");
	}
}

Скрипт 20

Результат выполнения шаблона получается в виде массива XmlElement, состоящего из единственного элемента, OuterXml которого показан ниже:


<Солянка xmlns:sql="urn:schemas-microsoft-com:xml-sql">
  <Employees EmployeeID="1" LastName="Davolio" FirstName="Nancy" Title="Sales Re
presentative" TitleOfCourtesy="Ms." ... />
  <Customers ContactName="Horst Kloss" Кол-во="28" /><Customers ContactName="Jos
e Pavarotti" Кол-во="31" /><Customers ContactName="Roland Mendel" Кол-во="30" />
  <Клиент Имя="Horst Kloss" Фирма="QUICK-Stop" Должность="Accounting Manager"><А
дрес><Страна>Germany</Страна><Город>Cunewalde</Город><Улица_дом>Taucherstra?e 10
</Улица_дом></Адрес><Заказы><Заказ Номер="10273"><Дата>1996-08-05</Дата><Стоимос
ть>76.07</Стоимость></Заказ><Заказ Номер="10285"><Дата>1996-08-20</Дата><Стоимос
ть>76.83</Стоимость></Заказ>...</Заказы></Клиент>
  <Сотрудник Фамилия="Fuller" Имя="Andrew"><Сотрудник Фамилия="Davolio" Имя="Nan
cy" /><Сотрудник Фамилия="Leverling" Имя="Janet" /><Сотрудник Фамилия="Peacock"
Имя="Margaret" /><Сотрудник Фамилия="Buchanan" Имя="Steven"><Сотрудник Фамилия="
Suyama" Имя="Michael" /><Сотрудник Фамилия="King" Имя="Robert" /><Сотрудник Фами
лия="Dodsworth" Имя="Anne" /></Сотрудник><Сотрудник Фамилия="Callahan" Имя="Laur
a" /></Сотрудник>
</Солянка>

DataSet как результат второго метода состоит из двух таблиц: Customers и Orders. Выбор Row Formatting = Nested на стадии определения метода Web-сервиса приводит к тому, что условие соединения таблиц в запросе (JOIN) переходит в свойство Relations объекта DataSet и позволяет для каждого клиента выбрать сделанные им заказы:


Таблица Customers
ContactName: Maria Larsson; ContactTitle: Owner; Customers_Id: 0; 
	Связанные записи из таблицы Orders
	OrderDate: 03.02.1997 0:00:00; Freight: 17.92; Customers_Id: 0; 
	OrderDate: 28.02.1997 0:00:00; Freight: 16.27; Customers_Id: 0; 
	OrderDate: 12.05.1997 0:00:00; Freight: 188.04; Customers_Id: 0; 
	OrderDate: 06.06.1997 0:00:00; Freight: 242.21; Customers_Id: 0; 

Таблица Customers
ContactName: Maria Anders; ContactTitle: Sales Representative; Customers_Id: 1; 
	Связанные записи из таблицы Orders
	OrderDate: 25.08.1997 0:00:00; Freight: 29.46; Customers_Id: 1; 
	OrderDate: 03.10.1997 0:00:00; Freight: 61.02; Customers_Id: 1; 
	OrderDate: 13.10.1997 0:00:00; Freight: 23.94; Customers_Id: 1; 

Таблица Customers
ContactName: Maria Larsson; ContactTitle: Owner; Customers_Id: 2; 
	Связанные записи из таблицы Orders
	OrderDate: 14.10.1997 0:00:00; Freight: 152.3; Customers_Id: 2; 
	OrderDate: 02.12.1997 0:00:00; Freight: 328.74; Customers_Id: 2; 
	OrderDate: 11.12.1997 0:00:00; Freight: 48.2; Customers_Id: 2; 
The program '[2460] ConsoleApplication1.exe' has exited with code 0 (0x0).

XML в MS SQL Server 2000 и технологиях доступа к данным | SQL Server как Web-сервис Дальше »
Rambler's Top100 Parking.ru Рейтинг@Mail.ru  Administrator: admin@sql.ru 
Last update: 07 окт 2003 
Hosted by uCoz