DataSet 是用断开式设计来构建的,其部分目的是为了便于通过 Internet 来传输数据。由于可以将 DataSet 和 DataTable 指定为 XML Web services 的输入或输出,并且无需进行其他任何编码即可在 XML Web services 和客户端之间将 DataSet 内容以流的形式来回传递,因此 DataSet 和 DataTable是“可序列化的”。DataSet 使用 DiffGram 格式隐式地转换为 XML 流,通过网络进行发送,然后在接收端从 XML 流重新构造为 DataSet。它为您使用 XML Web services 传输和返回关系数据提供了非常简单而灵活的方法。有关 DiffGram 格式的更多信息,请参阅 DiffGram。
以下示例显示创建 XML Web services 以及该服务客户端的步骤,其中会使用 DataSet 来传输关系数据(包含对该数据的修改),然后将所有更新解析回初始数据源。
创建返回和使用 DataSet 的 XML Web services
在本示例中,将创建返回数据(在本示例中为 Northwind 数据库中客户的列表)的 XML Web services,然后接收一个包含数据更新的 DataSet,XML Web services 会将更新解析回初始数据源。
XML Web services 公开两个方法:GetCustomers,它用于返回客户列表;UpdateCustomers,它用于将更新解析回数据源。XML Web services 存储在 Web 服务器上名为 DataSetSample.asmx 的文件中。以下代码将概括 DataSetSample.asmx 的内容。
[Visual
Basic]
<% @ 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 nwindConn As SqlConnection = New SqlConnection("Data
Source=localhost;Integrated Security=SSPI;Initial Catalog=northwind")
<WebMethod( Description := "Returns Northwind
Customers", EnableSession := False )> _
Public Function GetCustomers() As DataSet
Dim custDA As SqlDataAdapter = New
SqlDataAdapter("SELECT CustomerID, CompanyName FROM Customers",
nwindConn)
Dim custDS As DataSet = New DataSet()
custDA.MissingSchemaAction =
MissingSchemaAction.AddWithKey
custDA.Fill(custDS, "Customers")
GetCustomers = custDS
End Function
<WebMethod( Description := "Updates Northwind
Customers", EnableSession := False )> _
Public Function UpdateCustomers(custDS As DataSet) As DataSet
Dim custDA As SqlDataAdapter = New SqlDataAdapter()
custDA.InsertCommand = New SqlCommand("INSERT INTO
Customers (CustomerID, CompanyName) " & _
"Values(@CustomerID, @CompanyName)", nwindConn)
custDA.InsertCommand.Parameters.Add("@CustomerID",
SqlDbType.NChar, 5, "CustomerID")
custDA.InsertCommand.Parameters.Add("@CompanyName",
SqlDbType.NChar, 15, "CompanyName")
custDA.UpdateCommand = New SqlCommand("UPDATE
Customers Set CustomerID = @CustomerID, " & _
"CompanyName = @CompanyName WHERE CustomerID = @OldCustomerID",
nwindConn)
custDA.UpdateCommand.Parameters.Add("@CustomerID",
SqlDbType.NChar, 5, "CustomerID")
custDA.UpdateCommand.Parameters.Add("@CompanyName",
SqlDbType.NChar, 15, "CompanyName")
Dim myParm As SqlParameter =
custDA.UpdateCommand.Parameters.Add("@OldCustomerID",
SqlDbType.NChar, 5, "CustomerID")
myParm.SourceVersion = DataRowVersion.Original
custDA.DeleteCommand = New SqlCommand("DELETE FROM
Customers WHERE CustomerID = @CustomerID", nwindConn)
myParm = custDA.DeleteCommand.Parameters.Add("@CustomerID",
SqlDbType.NChar, 5, "CustomerID")
myParm.SourceVersion = DataRowVersion.Original
custDA.Update(custDS, "Customers")
UpdateCustomers = custDS
End Function
End Class
[C#]
<% @ 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 nwindConn = new SqlConnection("Data Source=localhost;Integrated
Security=SSPI;Initial Catalog=northwind");
[WebMethod( Description = "Returns Northwind Customers",
EnableSession = false )]
public DataSet GetCustomers()
{
SqlDataAdapter custDA = new SqlDataAdapter("SELECT
CustomerID, CompanyName FROM Customers", nwindConn);
DataSet custDS = new DataSet();
custDA.MissingSchemaAction =
MissingSchemaAction.AddWithKey;
custDA.Fill(custDS, "Customers");
return custDS;
}
[WebMethod( Description = "Updates Northwind Customers",
EnableSession = false )]
public DataSet UpdateCustomers(DataSet custDS)
{
SqlDataAdapter custDA = new SqlDataAdapter();
custDA.InsertCommand = new SqlCommand("INSERT INTO
Customers (CustomerID, CompanyName) " +
"Values(@CustomerID, @CompanyName)", nwindConn);
custDA.InsertCommand.Parameters.Add("@CustomerID",
SqlDbType.NChar, 5, "CustomerID");
custDA.InsertCommand.Parameters.Add("@CompanyName",
SqlDbType.NChar, 15, "CompanyName");
custDA.UpdateCommand = new SqlCommand("UPDATE
Customers Set CustomerID = @CustomerID, " +
"CompanyName = @CompanyName WHERE CustomerID = @OldCustomerID",
nwindConn);
custDA.UpdateCommand.Parameters.Add("@CustomerID",
SqlDbType.NChar, 5, "CustomerID");
custDA.UpdateCommand.Parameters.Add("@CompanyName",
SqlDbType.NChar, 15, "CompanyName");
SqlParameter myParm = custDA.UpdateCommand.Parameters.Add("@OldCustomerID",
SqlDbType.NChar, 5, "CustomerID");
myParm.SourceVersion = DataRowVersion.Original;
custDA.DeleteCommand = new SqlCommand("DELETE FROM
Customers WHERE CustomerID = @CustomerID", nwindConn);
myParm = custDA.DeleteCommand.Parameters.Add("@CustomerID",
SqlDbType.NChar, 5, "CustomerID");
myParm.SourceVersion = DataRowVersion.Original;
custDA.Update(custDS, "Customers");
return custDS;
}
}
在通常情况下,将编写 UpdateCustomers 方法来捕获开放式并发冲突。为了简单起见,以上示例没有包含此方法。有关开放式并发的更多信息,请参阅开放式并发。
XML Web services 的客户端将需要通过 SOAP
代理来使用公开的方法。代理可以使用
wsdl /l:VB /out:sample.vb http://myserver/data/DataSetSample.asmx /n:WebData.DSSample
若要在文件 sample.cs 中创建一个 C# 代理,请发出以下命令。
wsdl /:CS /out:sample.cs http://myserver/data/DataSetSample.asmx /n:WebData.DSSample
然后,可以将该代理编译为库并导入 XML Web services 客户端。若要编译在 sample.vb 中存储为 sample.dll 的 Visual Basic .NET 代理代码,请发出以下命令。
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 中存储为 sample.dll 的 C# 代理代码,请发出以下命令。
csc /t:library /out:sample.dll sample.cs /r:System.dll /r:System.Web.Services.dll /r:System.Data.dll /r:System.Xml.dll
当创建 XML Web services 代理后,可以将其导入客户端代码并使用 XML Web services 方法。以下代码示例导入该代理库,调用 GetCustomers 来获取客户列表,添加新客户,然后返回一个包含对 UpdateCustomers 的更新的 DataSet。请注意,该示例将 DataSet.GetChanges 所返回的 DataSet 传递给 UpdateCustomers,这是因为只有经过修改的行才需要传递给 UpdateCustomers。UpdateCustomers 返回已解析的 DataSet,然后,您可以将该 DataSet 合并 (Merge) 到现有 DataSet 中,以包含已解析的更改以及来自更新的任何行错误信息。
[Visual
Basic]
Imports System
Imports System.Data
Imports WebData.DSSample
Public Class Client
Public Shared Sub Main()
Dim mySamp As Sample = New Sample() ' Proxy object.
Dim myDS As DataSet = mySamp.GetCustomers()
Dim myTable As DataTable = myDS.Tables("Customers")
Dim newRow As DataRow = myTable.NewRow()
newRow("CustomerID") = "ABCDE"
newRow("CompanyName") = "New Company
Name"
myTable.Rows.Add(newRow)
Dim updDS As DataSet =
mySamp.UpdateCustomers(myDS.GetChanges())
myDS.Merge(updDS)
myDS.AcceptChanges()
End Sub
End Class
[C#]
using System;
using System.Data;
using WebData.DSSample;
public class Client
{
public static void Main()
{
Sample mySamp = new Sample(); // Proxy object.
DataSet myDS = mySamp.GetCustomers();
DataTable myTable = myDS.Tables["Customers"];
DataRow newRow = myTable.NewRow();
newRow["CustomerID"] = "ABCDE";
newRow["CompanyName"] = "New Company
Name";
myTable.Rows.Add(newRow);
DataSet updDS = new DataSet();
updDS = mySamp.UpdateCustomers(myDS.GetChanges());
myDS.Merge(updDS);
myDS.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