Использование набора данных из веб-службы XML

Проект DataSet был разработан с отсоединяемой конструкцией, отчасти для упрощения удобного транспорта данных через Интернет. Сериализуемый DataSet это означает, что он может быть указан в качестве входных или выходных данных веб-служб XML без необходимости дополнительной кодировки для потоковой передачи содержимого DataSet из веб-службы XML клиенту и обратно. DataSet неявно преобразуется в XML-поток с помощью формата DiffGram, отправляемого по сети, а затем реконструируется из XML-потока на принимающей стороне как DataSet. Это дает простой и гибкий метод для передачи и возврата реляционных данных с помощью веб-служб XML. Дополнительные сведения о формате DiffGram см. в разделе DiffGrams.

В следующем примере показано, как создать веб-службу XML и клиент, которые используют DataSet для передачи реляционных данных (включая измененные данные) и разрешают все обновления обратно в исходный источник данных.

Замечание

Передача экземпляров DataSet или DataTable в рамках вызовов веб-службы XML небезопасна, если входные данные не являются доверенными. Дополнительные сведения см. в статье Руководство по безопасности для DataSet и DataTable. Мы также рекомендуем всегда учитывать последствия безопасности при создании веб-службы XML. Сведения о защите веб-службы XML см. в разделе "Защита веб-служб XML, созданных с помощью ASP.NET".

Создание веб-службы XML

  1. Создайте веб-службу XML.

    В этом примере создается XML-веб-служба, которая возвращает данные, в данном случае список клиентов из Northwind базы данных, и принимает DataSet с обновлениями данных, которые веб-служба разрешает обратно в исходный источник данных.

    Веб-служба XML предоставляет два метода: GetCustomers, чтобы вернуть список клиентов и UpdateCustomers, чтобы устранить обновления обратно в источник данных. Веб-служба XML хранится в файле на веб-сервере с именем DataSetSample.asmx. Следующий код описывает содержимое DataSetSample.asmx.

    <% @ WebService Language = "vb" Class = "Sample" %>
    Imports System
    Imports System.Data
    Imports System.Data.SqlClient
    Imports System.Web.Services
    
    <WebService(Namespace:="http://microsoft.com/webservices/")> _
    Public Class Sample
    
    Public connection As SqlConnection = New SqlConnection("Data Source=(local);Integrated Security=SSPI;Initial Catalog=Northwind")
    
      <WebMethod( Description := "Returns Northwind Customers", EnableSession := False )> _
      Public Function GetCustomers() As DataSet
        Dim adapter As SqlDataAdapter = New SqlDataAdapter( _
          "SELECT CustomerID, CompanyName FROM Customers", connection)
    
        Dim custDS As DataSet = New DataSet()
        adapter.MissingSchemaAction = MissingSchemaAction.AddWithKey
        adapter.Fill(custDS, "Customers")
    
        Return custDS
      End Function
    
      <WebMethod( Description := "Updates Northwind Customers", EnableSession := False )> _
      Public Function UpdateCustomers(custDS As DataSet) As DataSet
        Dim adapter As SqlDataAdapter = New SqlDataAdapter()
    
        adapter.InsertCommand = New SqlCommand( _
          "INSERT INTO Customers (CustomerID, CompanyName) " & _
          "Values(@CustomerID, @CompanyName)", connection)
        adapter.InsertCommand.Parameters.Add( _
          "@CustomerID", SqlDbType.NChar, 5, "CustomerID")
        adapter.InsertCommand.Parameters.Add( _
          "@CompanyName", SqlDbType.NChar, 15, "CompanyName")
    
        adapter.UpdateCommand = New SqlCommand( _
          "UPDATE Customers Set CustomerID = @CustomerID, " & _
          "CompanyName = @CompanyName WHERE CustomerID = " & _
          @OldCustomerID", connection)
        adapter.UpdateCommand.Parameters.Add( _
          "@CustomerID", SqlDbType.NChar, 5, "CustomerID")
        adapter.UpdateCommand.Parameters.Add( _
          "@CompanyName", SqlDbType.NChar, 15, "CompanyName")
    
        Dim parameter As SqlParameter = _
          adapter.UpdateCommand.Parameters.Add( _
          "@OldCustomerID", SqlDbType.NChar, 5, "CustomerID")
        parameter.SourceVersion = DataRowVersion.Original
    
        adapter.DeleteCommand = New SqlCommand( _
          "DELETE FROM Customers WHERE CustomerID = @CustomerID", _
          connection)
        parameter = adapter.DeleteCommand.Parameters.Add( _
          "@CustomerID", SqlDbType.NChar, 5, "CustomerID")
        parameter.SourceVersion = DataRowVersion.Original
    
        adapter.Update(custDS, "Customers")
    
        Return custDS
      End Function
    End Class
    
    <% @ WebService Language = "C#" Class = "Sample" %>
    using System;
    using System.Data;
    using System.Data.SqlClient;
    using System.Web.Services;
    
    [WebService(Namespace="http://microsoft.com/webservices/")]
    public class Sample
    {
      public SqlConnection connection = new SqlConnection("Data Source=(local);Integrated Security=SSPI;Initial Catalog=Northwind");
    
      [WebMethod( Description = "Returns Northwind Customers", EnableSession = false )]
      public DataSet GetCustomers()
      {
        SqlDataAdapter adapter = new SqlDataAdapter(
          "SELECT CustomerID, CompanyName FROM Customers", connection);
    
        DataSet custDS = new DataSet();
        adapter.MissingSchemaAction = MissingSchemaAction.AddWithKey;
        adapter.Fill(custDS, "Customers");
    
        return custDS;
      }
    
      [WebMethod( Description = "Updates Northwind Customers",
        EnableSession = false )]
      public DataSet UpdateCustomers(DataSet custDS)
      {
        SqlDataAdapter adapter = new SqlDataAdapter();
    
        adapter.InsertCommand = new SqlCommand(
          "INSERT INTO Customers (CustomerID, CompanyName) " +
          "Values(@CustomerID, @CompanyName)", connection);
        adapter.InsertCommand.Parameters.Add(
          "@CustomerID", SqlDbType.NChar, 5, "CustomerID");
        adapter.InsertCommand.Parameters.Add(
          "@CompanyName", SqlDbType.NChar, 15, "CompanyName");
    
        adapter.UpdateCommand = new SqlCommand(
          "UPDATE Customers Set CustomerID = @CustomerID, " +
          "CompanyName = @CompanyName WHERE CustomerID = " +
          "@OldCustomerID", connection);
        adapter.UpdateCommand.Parameters.Add(
          "@CustomerID", SqlDbType.NChar, 5, "CustomerID");
        adapter.UpdateCommand.Parameters.Add(
          "@CompanyName", SqlDbType.NChar, 15, "CompanyName");
        SqlParameter parameter = adapter.UpdateCommand.Parameters.Add(
          "@OldCustomerID", SqlDbType.NChar, 5, "CustomerID");
        parameter.SourceVersion = DataRowVersion.Original;
    
        adapter.DeleteCommand = new SqlCommand(
        "DELETE FROM Customers WHERE CustomerID = @CustomerID",
         connection);
        parameter = adapter.DeleteCommand.Parameters.Add(
          "@CustomerID", SqlDbType.NChar, 5, "CustomerID");
        parameter.SourceVersion = DataRowVersion.Original;
    
        adapter.Update(custDS, "Customers");
    
        return custDS;
      }
    }
    

    В типичном сценарии метод UpdateCustomers будет разработан для перехвата оптимистических нарушений параллелизма. Для простоты пример не включает это. Дополнительные сведения об оптимистическом параллелизме см. в разделе "Оптимистическое параллелизм".

  2. Создайте прокси-сервер веб-службы XML.

    Для использования предоставляемых методов клиентам веб-службы XML требуется прокси-сервер SOAP. Вы можете создать этот прокси-сервер в Visual Studio. Задав веб-ссылку на существующую веб-службу из Visual Studio, все поведение, описанное на этом шаге, происходит прозрачно. Если вы хотите создать класс прокси-сервера самостоятельно, перейдите к этому обсуждению. Однако в большинстве случаев для создания прокси-класса для клиентского приложения достаточно использовать Visual Studio.

    Прокси-сервер можно создать с помощью средства языка описания веб-служб. Например, если веб-служба XML предоставляется по URL-адресу http://myserver/data/DataSetSample.asmx, выполните команду, например следующую, чтобы создать прокси-сервер .NET Visual Basic с пространством имен WebData.DSSample и сохранить его в файле sample.vb.

    wsdl /l:VB -out:sample.vb http://myserver/data/DataSetSample.asmx /n:WebData.DSSample
    

    Чтобы создать прокси-сервер C# в файле sample.cs, выполните следующую команду.

    wsdl -l:CS -out:sample.cs http://myserver/data/DataSetSample.asmx -n:WebData.DSSample
    

    Затем прокси-сервер можно скомпилировать как библиотеку и импортировать в клиент веб-службы XML. Чтобы скомпилировать прокси-код Visual Basic .NET, хранящийся в sample.vb как sample.dll, выполните следующую команду.

    vbc -t:library -out:sample.dll sample.vb -r:System.dll -r:System.Web.Services.dll -r:System.Data.dll -r:System.Xml.dll
    

    Чтобы скомпилировать прокси-код C#, хранящийся в sample.cs как sample.dll, выполните следующую команду.

    csc -t:library -out:sample.dll sample.cs -r:System.dll -r:System.Web.Services.dll -r:System.Data.dll -r:System.Xml.dll
    
  3. Создайте клиент веб-службы XML.

    Если вы хотите, чтобы Visual Studio сгенерировала для вас класс-прокси веб-службы, просто создайте клиентский проект и в окне обозревателя решений щелкните проект правой кнопкой мыши, затем выберите Add>Ссылка на службу. В диалоговом окне "Добавить ссылку на службу " выберите "Дополнительно" и выберите "Добавить веб-ссылку". Выберите веб-службу из списка доступных веб-служб (это может потребовать предоставления адреса конечной точки веб-службы, если веб-служба недоступна в текущем решении или на текущем компьютере). При создании прокси-сервера веб-службы XML (как описано на предыдущем шаге), его можно импортировать в клиентский код и использовать методы веб-службы XML.

    Следующий пример кода импортирует прокси-библиотеку, вызывает GetCustomers, чтобы получить список клиентов, добавляет нового клиента, а затем возвращает DataSet с обновлениями для UpdateCustomers.

    В этом примере DataSet передается результат вызова DataSet.GetChangesUpdateCustomers, так как в UpdateCustomers нужно передать только измененные строки. UpdateCustomers возвращает разрешённый набор данных, который можно затем Merge в существующий DataSet, чтобы интегрировать разрешённые изменения и любые сведения об ошибках строк из обновления. В следующем коде предполагается, что вы использовали Visual Studio для создания веб-ссылки и переименовали веб-ссылку на DsSample в диалоговом окне "Добавление веб-ссылки ".

    Imports System
    Imports System.Data
    
    Public Class Client
    
      Public Shared Sub Main()
        Dim proxySample As New DsSample.Sample ()  ' Proxy object.
        Dim customersDataSet As DataSet = proxySample.GetCustomers()
        Dim customersTable As DataTable = _
          customersDataSet.Tables("Customers")
    
        Dim rowAs DataRow = customersTable.NewRow()
        row("CustomerID") = "ABCDE"
        row("CompanyName") = "New Company Name"
        customersTable.Rows.Add(row)
    
        Dim updateDataSet As DataSet = _
          proxySample.UpdateCustomers(customersDataSet.GetChanges())
    
        customersDataSet.Merge(updateDataSet)
        customersDataSet.AcceptChanges()
      End Sub
    End Class
    
    using System;
    using System.Data;
    
    public class Client
    {
      public static void Main()
      {
        Sample proxySample = new DsSample.Sample();  // Proxy object.
        DataSet customersDataSet = proxySample.GetCustomers();
        DataTable customersTable = customersDataSet.Tables["Customers"];
    
        DataRow row = customersTable.NewRow();
        row["CustomerID"] = "ABCDE";
        row["CompanyName"] = "New Company Name";
        customersTable.Rows.Add(row);
    
        DataSet updateDataSet = new DataSet();
    
        updateDataSet =
          proxySample.UpdateCustomers(customersDataSet.GetChanges());
    
        customersDataSet.Merge(updateDataSet);
        customersDataSet.AcceptChanges();
      }
    }
    

    Если вы решите создать класс прокси-сервера самостоятельно, необходимо выполнить следующие дополнительные действия. Чтобы скомпилировать пример, укажите созданную прокси-библиотеку (sample.dll) и связанные библиотеки .NET. Чтобы скомпилировать версию примера Visual Basic .NET, хранящуюся в файле client.vb, выполните следующую команду.

    vbc client.vb -r:sample.dll -r:System.dll -r:System.Data.dll -r:System.Xml.dll -r:System.Web.Services.dll
    

    Чтобы скомпилировать версию примера C#, хранящуюся в файле client.cs, выполните следующую команду.

    csc client.cs -r:sample.dll -r:System.dll -r:System.Data.dll -r:System.Xml.dll -r:System.Web.Services.dll
    

См. также