WCF分布式开发步步为赢(8):使用数据集(DataSet)、数据表(DataTable)、集合(Collection)传递数据
- 通过 DataAdapter 使用数据源中的数据生成和填充 DataSet 中的每个 DataTable。
- 通过添加、更新或删除 DataRow 对象更改单个 DataTable 对象中的数据。
- 调用 GetChanges 方法以创建只反映对数据进行的更改的第二个 DataSet。
- 调用 DataAdapter 的 Update 方法,并将第二个 DataSet 作为参数传递。
- 调用 Merge 方法将第二个 DataSet 中的更改合并到第一个中。
- 针对 DataSet 调用 AcceptChanges。或者,调用 RejectChanges 以取消更改。
DataSet 和 DataTable 对象从 MarshalByValueComponent 继承而来,并支持用于远程处理的 ISerializable 接口。这些是仅有的可以远程处理的 ADO.NET 对象。 我们先来看一下DataSet的定义,使用Reflector工具查看,部分代码如下:
public class DataSet : MarshalByValueComponent, IListSource, IXmlSerializable, ISupportInitializeNotification, ISupportInitialize, ISerializable
{
// Fields
private bool _caseSensitive;
private CultureInfo _culture;
private bool _cultureUserSet;
private string _datasetPrefix;
private object _defaultViewManagerLock;
private readonly int _objectID;
private static int _objectTypeCount;
private SerializationFormat _remotingFormat;
private string dataSetName;
private DataViewManager defaultViewManager;
private bool enforceConstraints;
internal PropertyCollection extendedProperties;
private bool fBoundToDocument;
internal bool fEnableCascading;
internal bool fInitInProgress;

}
public class DataTable : MarshalByValueComponent, IListSource, ISupportInitializeNotification, ISupportInitialize, ISerializable, IXmlSerializable
{
// Fields
private bool _caseSensitive;
private bool _caseSensitiveUserSet;
internal DataColumn _colUnique;
private CompareOptions _compareFlags;
private CompareInfo _compareInfo;

}
// 因此本例开头使用 using 语句来引用该命名空间。
// 为了掩饰WCF服务的操作重载
namespace WCFService
{
// 1.服务契约,操作契约重载
[ServiceContract(Namespace = " http://www.cnblogs.com/frank_xl/ " )]
interface IWCFService
{
// 操作契约,数据表
[OperationContract]
System.Data.DataTable GetDataByTable();
// 操作契约,数据集
[OperationContract]
System.Data.DataSet GetDataByDataSet();
// 操作契约,数据集合
[OperationContract]
List < User > GetDataByCollection();
}
// 2.服务类,集成接口。实现契约
public class WCFService : IWCFService
{
// 实现接口定义的方法,DataTable传递数据
public System.Data.DataTable GetDataByTable()
{
// 这里可以定义数据持久化操作,访问数据库等
System.Data.DataSet dataSet = new System.Data.DataSet();
System.Data.DataTable dataTable = null ;
SqlConnection sqlConnection = new SqlConnection( " Data Source=.\\SQLEXPRESS;AttachDbFilename=|DataDirectory|\\Database\\DatabaseWCF.mdf;Integrated Security=True;User Instance=True " );
try
{
System.Data.SqlClient.SqlDataAdapter sqlDataAdapter = new System.Data.SqlClient.SqlDataAdapter( " SELECT id, name, english_name FROM TableWCF " , sqlConnection);
sqlDataAdapter.Fill(dataSet, " TableWCF " );
if (dataSet != null && dataSet.Tables.Count > 0 )
{
dataTable = dataSet.Tables[ 0 ];
}
}
catch (Exception e)
{
}
finally
{
sqlConnection.Close();
}
Console.WriteLine( " Calling WCF Service,Transfer data using DataTable " );
return dataTable;
}
// 实现接口定义的方法,DataSet传递数据
public System.Data.DataSet GetDataByDataSet()
{
// 这里可以定义数据持久化操作,访问数据库等
System.Data.DataSet dataSet = new System.Data.DataSet();
SqlConnection sqlConnection = new SqlConnection( " Data Source=.\\SQLEXPRESS;AttachDbFilename=|DataDirectory|\\Database\\DatabaseWCF.mdf;Integrated Security=True;User Instance=True " );
try
{
System.Data.SqlClient.SqlDataAdapter sqlDataAdapter = new System.Data.SqlClient.SqlDataAdapter( " SELECT id, name, english_name FROM TableWCF " , sqlConnection);
sqlDataAdapter.Fill(dataSet, " TableWCF " );
}
catch (Exception e)
{
}
finally
{
sqlConnection.Close();
}
Console.WriteLine( " Calling WCF Service,Transfer data using dataSet " );
return dataSet;
}
// 实现接口定义的方法,Collection传递数据
public List < User > GetDataByCollection()
{
// 这里可以定义数据持久化操作,访问数据库等
List < User > list = new List < User > ();
for ( int i = 0 ; i < 10 ; i ++ )
{
User user = new User();
user.age = 20 + i;
user.name = " Frank Xu Lei: " + i.ToString();
}
Console.WriteLine( " Calling WCF Service,Transfer data using Collection " );
return list;
}
}
// 3数据契约
[DataContract]
public class User
{
[DataMember]
public string name;
[DataMember]
public int age;
}
}
< service behaviorConfiguration = " WCFService.WCFServiceBehavior " name = " WCFService.WCFService " >
< endpoint
address = " http://localhost:9003/WCFService "
binding = " wsHttpBinding "
contract = " WCFService.IWCFService " >
</ endpoint >
< endpoint address = " mex " binding = " mexHttpBinding " contract = " IMetadataExchange " />
< host >
< baseAddresses >
< add baseAddress = " http://localhost:9003/ " />
</ baseAddresses >
</ host >
</ service >
</ services >
< behaviors >
< serviceBehaviors >
< behavior name = " WCFService.WCFServiceBehavior " >
< serviceMetadata httpGetEnabled = " true " />
< serviceDebug includeExceptionDetailInFaults = " false " />
</ behavior >
</ serviceBehaviors >
</ behaviors >
return base .Channel.GetDataByTable();
}
public System.Data.DataSet GetDataByDataSet() {
return base .Channel.GetDataByDataSet();
}
return base .Channel.GetDataByCollection();
}
private void buttonDataTable_Click( object sender, EventArgs e)
{
WCFServiceClient wcfServiceProxy =
new WCFServiceClient( " WSHttpBinding_IWCFService " );
// 调用服务,获取数据表dataTable,
System.Data.DataTable dataTable = wcfServiceProxy.GetDataByTable();
if (dataTable != null )
{
dataGridViewWCFDataTable.DataSource = dataTable; // 绑定数据源到控件
}
}
// Get data using DataSet By WCF proxy
private void buttonDataSet_Click( object sender, EventArgs e)
{
WCFServiceClient wcfServiceProxy =
new WCFServiceClient( " WSHttpBinding_IWCFService " );
// 调用服务,获取数据集dataSet,
System.Data.DataSet dataSet = wcfServiceProxy.GetDataByDataSet();
if (dataSet != null && dataSet.Tables.Count > 0 )
{
dataGridViewWCFDataSet.DataSource = dataSet.Tables[ 0 ]; // 绑定数据源到控件
}
}
4.《Programming in WCF Service》