Consumir DataSet a partir de un servicio web XML (ADO.NET)

Actualización: November 2007

La arquitectura del DataSet tiene un diseño desconectado, en parte para facilitar el transporte de datos a través de Internet. DataSet es "serializable" en el sentido de que puede especificarse como entrada o como salida de servicios web XML sin necesidad de programación adicional para transmitir en secuencia el contenido del DataSet desde un servicio web XML a un cliente y viceversa. El DataSet se convierte implícitamente en una secuencia XML mediante el formato DiffGram, se envía a través de la red y se reconstruye a partir de la secuencia XML como un DataSet del extremo receptor. Esto proporciona un método muy sencillo y flexible para transmitir y devolver datos relacionales mediante servicios web XML. Para obtener más información acerca del formato DiffGram, vea DiffGrams (ADO.NET).

En el siguiente ejemplo se muestra cómo crear un servicio web XML y un cliente que utilice DataSet para transportar datos relacionales (incluyendo datos modificados) y resolver cualquier actualización en el origen de datos inicial.

Nota:

Al crear un servicio web XML, es recomendable tener siempre en cuenta las implicaciones de seguridad. Para obtener información sobre cómo proteger un servicio web XML, vea Proteger servicios web XML creados con ASP.NET.

Para crear un servicio web XML que devuelve y consume un DataSet

  1. Cree el servicio web XML.

    En el ejemplo se crea un servicio web XML que devuelve datos, una lista de clientes de la base de datos Northwind, y recibe un DataSet con actualizaciones relacionadas con los datos que el servicio web XML resuelve y devuelve al origen de datos inicial.

    El servicio web XML expone dos métodos: GetCustomers, para devolver la lista de clientes, y UpdateCustomers, para resolver las actualizaciones en el origen de datos. El servicio web XML se almacena en un archivo del servidor web denominado DataSetSample.asmx. En el siguiente código se describe el contenido de DataSetSample.asmx.

    <% @ WebService Language = "vb" Class = "Sample" %>
    Imports System
    Imports System.Data
    Imports System.Data.SqlClient
    Imports System.Web.Services
    
    <WebService(Namespace:="https://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="https://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;
      }
    }
    

    En una situación típica, se escribiría el método UpdateCustomers para detectar infracciones de la simultaneidad optimista. Para simplificar, el ejemplo no lo incluye. Para obtener más información acerca de la simultaneidad optimista, vea Simultaneidad optimista (ADO.NET).

  2. Cree un proxy de servicio web XML.

    Los clientes del servicio web XML necesitan un proxy SOAP para utilizar los métodos expuestos. Visual Studio puede generar el proxy. Al establecer una referencia web a un servicio web existente desde Visual Studio, el comportamiento descrito en este paso se produce de forma transparente. Si desea crear la clase de proxy personalmente, continúe con la explicación. Sin embargo, el uso de Visual Studio para crear la clase de proxy para la aplicación cliente es suficiente en la mayoría de los casos.

    Es posible crear un proxy con la herramienta Lenguaje de descripción de servicios web. Por ejemplo, si el servicio web XML se expone en la dirección URL http://myserver/data/DataSetSample.asmx, hay que utilizar un comando como el siguiente para crear un proxy de Visual Basic .NET con un espacio de nombres de WebData.DSSample y almacenarlo en el archivo sample.vb.

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

    Para crear un proxy de C# en el archivo sample.cs, hay que utilizar el comando siguiente.

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

    El proxy puede compilarse como una biblioteca e importarse en el cliente del servicio web XML. Para compilar el código de proxy de Visual Basic .NET almacenado en sample.vb como sample.dll, hay que utilizar el siguiente comando.

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

    Para compilar el código de proxy de C# almacenado en sample.cs como sample.dll, hay que utilizar el siguiente comando.

    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. Cree un cliente de servicio web XML.

    Si desea que Visual Studio genere la clase de proxy del servicio web, cree el proyecto cliente y, en la ventana del Explorador de soluciones, haga clic con el botón secundario del mouse en el proyecto; a continuación, haga clic en Agregar referencia web y seleccione el servicio web en la lista de servicios web disponibles. Puede que sea necesario proporcionar la dirección del punto final de servicios web, en caso de que el servicio web no se encuentre disponible en la solución o en el equipo actuales. Si crea el proxy del servicio web XML personalmente, tal y como se describe en el paso anterior, puede importarlo en el código de cliente y utilizar los métodos de servicio web XML. En el siguiente ejemplo de código se importa la biblioteca de proxy, se llama a GetCustomers para obtener una lista de clientes, se agrega un nuevo cliente y se devuelve un DataSet con las actualizaciones aUpdateCustomers.

    Tenga en cuenta que en el ejemplo se pasa el DataSet devuelto por DataSet.GetChanges a UpdateCustomers, ya que sólo es necesario pasar a UpdateCustomers las filas modificadas. UpdateCustomers devuelve el DataSet resuelto, que puede Merge con el DataSet existente para incorporar los cambios resueltos y cualquier información de error de fila de la actualización. En el código siguiente se da por sentado que se ha utilizado Visual Studio para crear la referencia web y que se ha cambiado el nombre de la misma a DsSample en el cuadro de diálogo Agregar referencia web.

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

    Si decide crear la clase de proxy personalmente, debe seguir los pasos adicionales que se describen a continuación. Para compilar el ejemplo, indique la biblioteca de proxy creada (sample.dll) y las bibliotecas de .NET relacionadas. Para compilar la versión de Visual Basic .NET del ejemplo, almacenada en el archivo client.vb, hay que utilizar el comando siguiente.

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

    Para compilar la versión de C# del ejemplo, almacenada en el archivo client.cs, hay que utilizar el comando siguiente.

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

Vea también

Conceptos

Rellenar un objeto DataSet desde un objeto DataAdapter (ADO.NET)

Actualizar orígenes de datos con DataAdapters (ADO.NET)

Parámetros DataAdapter (ADO.NET)

Referencia

Herramienta Lenguaje de descripción de servicios Web (Wsdl.exe)

Otros recursos

ADO.NET

DataSets, DataTables y DataViews (ADO.NET)

DataTables (ADO.NET)