从 XML Web 服务使用 DataSet

DataSet 架构采用断开连接的设计,部分原因是为了方便通过 Internet 传输数据。 DataSet 是“可序列化的”,因为它可以指定为 XML Web 服务的输入或输出,而无需任何其他编码才能将数据集的内容从 XML Web 服务流式传输到客户端和回退。 DataSet 使用 DiffGram 格式隐式转换为 XML 流,通过网络发送,然后从 XML 流重新构造为接收端的数据集。 这为你提供了一种简单灵活的方法来使用 XML Web 服务传输和返回关系数据。 有关 DiffGram 格式的详细信息,请参阅 DiffGrams

以下示例演示如何创建一个 XML Web 服务和客户端,该 服务使用数据集 传输关系数据(包括修改的数据),并将任何更新解析回原始数据源。

注释

作为 XML Web 服务调用的一部分传输DataSetDataTable实例,如果输入不受信任,则是不安全的。 有关详细信息,请参阅 DataSet 和 DataTable 安全指南。 我们还建议在创建 XML Web 服务时始终考虑安全隐患。 有关保护 XML Web 服务的信息,请参阅 保护使用 ASP.NET 创建的 XML Web 服务

创建 XML Web 服务

  1. 创建 XML Web 服务。

    在此示例中,将创建一个 XML Web 服务来返回数据,在本例中返回 来自 Northwind 数据库的客户列表,并接收一个包含数据更新的 数据集 ,XML Web 服务会解析回原始数据源。

    XML Web 服务公开两种方法: GetCustomers、返回客户列表和 UpdateCustomers,以将更新解析回数据源。 XML Web 服务存储在名为 DataSetSample.asmx 的 Web 服务器上的文件中。 以下代码概述了 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 Web 服务代理。

    XML Web 服务的客户端需要 SOAP 代理才能使用公开的方法。 你可以让 Visual Studio 为你生成此代理。 通过从 Visual Studio 中设置对现有 Web 服务的 Web 引用,此步骤中所述的所有行为都是透明的。 如果要自行创建代理类,请继续讨论。 但是,在大多数情况下,使用 Visual Studio 为客户端应用程序创建代理类已足够。

    可以使用 Web 服务描述语言工具创建代理。 例如,如果 XML Web 服务在 URL http://myserver/data/DataSetSample.asmx中公开,请发出如下命令,以创建包含 WebData.DSSample 命名空间的 Visual Basic .NET 代理并将其存储在文件sample.vb中。

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

    若要在文件sample.cs中创建 C# 代理,请发出以下命令。

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

    然后,可以将代理编译为库并导入 XML Web 服务客户端。 若要将存储在 sample.vb 中的 Visual Basic .NET 代理代码编译为 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  
    

    若要将存储在sample.cs中的 C# 代理代码编译为 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 Web 服务客户端。

    如果要让 Visual Studio 为你生成 Web 服务代理类,只需创建客户端项目,然后在“解决方案资源管理器”窗口中右键单击该项目,然后选择“ 添加>服务引用”。 在 “添加服务引用 ”对话框中,选择“ 高级”,然后选择“ 添加 Web 引用”。 从可用的 Web 服务列表中选择 Web 服务(如果 Web 服务在当前解决方案或当前计算机上不可用,则可能需要提供 Web 服务终结点的地址)。 如果自行创建 XML Web 服务代理(如上一步中所述),则可以将其导入客户端代码并使用 XML Web 服务方法。

    以下示例代码导入代理库,调用 GetCustomers 获取客户列表,添加新客户,然后返回包含 UpdateCustomers 更新的数据集

    该示例将 DataSet.GetChanges 返回的 DataSet 传递给 UpdateCustomers,因为只需要将修改的行传递给 UpdateCustomersUpdateCustomers 返回已解析的 数据集,然后你可以 将其合并 到现有的 数据集 中,以合并已解决的更改以及更新中的任何行错误信息。 以下代码假定你已使用 Visual Studio 创建 Web 引用,并且已在 “添加 Web 引用 ”对话框中重命名了对 DsSample 的 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();  
      }  
    }  
    

    如果你决定自己创建代理类,则必须执行以下额外步骤。 若要编译示例,请提供创建的代理库(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  
    

另请参阅