数据集(DataSet)、数据表(DataTable)、集合(Collection)概念是.NET FrameWork里提供数据类型,在应用程序编程过程中会经常使用其来作为数据的载体,属于ADO.NET的一部分。今天我们WCF分布式开发步步为赢第8节的内容:使用数据集(DataSet)、数据表(DataTable)、集合(Collection)传递数据。本节内容除了介绍几个类型概念外的,同样会详细给出代码的实现过程。此外我们会分析这几种数据类型的优势和缺点,以及在面向对象的服务开发过程中如何解决这些问题。

(昨天博客园发布文章出错,没办法只有现在重新发了,可惜我花了很久排版,没保存成功,结果还是要重新组织。大家有好的方法可以介绍一下~)

【1】数据集(DataSet)、数据表(DataTable):

我们首先来介绍这两个类型的相关概念,然后在介绍其在WCF应用程序开发中的使用方式。

【1.1】基本概念:

数据集(DataSet)、数据表(DataTable),相信大家都不回陌生,只要做过ADO.NET进行数据库编程的开发人员来说,都会使用到这两个类。DataSet 是 ADO.NET 结构的主要组件,它是从数据源中检索到的数据在内存中的缓存。DataSet 由一组 DataTable 对象组成,您可使这些对象与 DataRelation 对象互相关联。您还可通过使用 UniqueConstraint 和 ForeignKeyConstraint 对象在 DataSet 中实施数据完整性。有关使用 DataSet 对象的详细信息,请参见 在 ADO.NET 中使用 DataSet。

尽管 DataTable 对象中包含数据,但是 DataRelationCollection 允许您遍览表的层次结构。这些表包含在通过 Tables 属性访问的 DataTableCollection 中。当访问 DataTable 对象时,请注意它们是按条件区分大小写的。例如,如果一个 DataTable 被命名为“mydatatable”,另一个被命名为“Mydatatable”,则用于搜索其中一个表的字符串被认为是区分大小写的。但是,如果“mydatatable”存在而“Mydatatable”不存在,则认为该搜索字符串不区分大小写。有关使用 DataTable 对象的更多信息,请参见 创建 DataTable。

DataSet 可将数据和架构作为 XML 文档进行读写。数据和架构可通过 HTTP 传输,并在支持 XML 的任何平台上被任何应用程序使用。可使用 WriteXmlSchema 方法将架构保存为 XML 架构,并且可以使用 WriteXml 方法保存架构和数据。若要读取既包含架构也包含数据的 XML 文档,请使用 ReadXml 方法。

在典型的多层实现中,用于创建和刷新 DataSet 并依次更新原始数据的步骤包括:

  1. 通过 DataAdapter 使用数据源中的数据生成和填充 DataSet 中的每个 DataTable。
  2. 通过添加、更新或删除 DataRow 对象更改单个 DataTable 对象中的数据。
  3. 调用 GetChanges 方法以创建只反映对数据进行的更改的第二个 DataSet。
  4. 调用 DataAdapter 的 Update 方法,并将第二个 DataSet 作为参数传递。
  5. 调用 Merge 方法将第二个 DataSet 中的更改合并到第一个中。
  6. 针对 DataSet 调用 AcceptChanges。或者,调用 RejectChanges 以取消更改。

【1.2】     DataSet 和 DataTable 对象从 MarshalByValueComponent 继承而来,并支持用于远程处理的 ISerializable 接口。这些是仅有的可以远程处理的 ADO.NET 对象。   我们先来看一下DataSet的定义,使用Reflector工具查看,部分代码如下:

Serializable, ToolboxItem("Microsoft.VSDesigner.Data.VS.DataSetToolboxItem, Microsoft.VSDesigner, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"), DefaultProperty("DataSetName"), XmlSchemaProvider("GetDataSetSchema"), ResDescription("DataSetDescr"), XmlRoot("DataSet"), Designer("Microsoft.VSDesigner.Data.VS.DataSetDesigner, Microsoft.VSDesigner, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]
public class DataSet : MarshalByValueComponent, IListSource, IXmlSerializable, ISupportInitializeNotification, ISupportInitialize, ISerializable
{// Fieldsprivate 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;}

DataTable的部分实现代码如下:

[Serializable, Editor("Microsoft.VSDesigner.Data.Design.DataTableEditor, Microsoft.VSDesigner, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.Drawing.Design.UITypeEditor, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"), DefaultProperty("TableName"), DesignTimeVisible(false), ToolboxItem(false), XmlSchemaProvider("GetDataTableSchema"), DefaultEvent("RowChanging")]
public class DataTable : MarshalByValueComponent, IListSource, ISupportInitializeNotification, ISupportInitialize, ISerializable, IXmlSerializable
{// Fieldsprivate bool _caseSensitive;private bool _caseSensitiveUserSet;internal DataColumn _colUnique;private CompareOptions _compareFlags;private CompareInfo _compareInfo;}

在WCF分布式应用程序开发过程中,可以使用来作为数据契约类型,在服务和客户端传递。两者在定义之初都包含了[Serializable]声明,因此两者的对象都是可以序列化的。可以使用在客户端和服务端传递数据。

【2】集合(Collection):

集合也是我们编程开发中经常使用的类型。

【2.1】基本概念:

.NET Framework 提供了用于数据存储和检索的专用类。这些类提供对堆栈、队列、列表和哈希表的支持。大多数集合类实现相同的接口,可继承这些接口来创建适应更为专业的数据存储需要的新集合类。针对 .NET Framework 的 2.0 版和更高版本的应用程序应当使用 System.Collections.Generic 命名空间中的泛型集合类,与对应的非泛型类相比,这些类提供了更高的类型安全性和效率。

集合类具有以下特点:

集合类定义为 System.Collections 或 System.Collections.Generic 命名空间的一部分。大多数集合类都派生自 违规广告ection、IComparer、IEnumerable、IList、IDictionary 和 IDictionaryEnumerator 接口以及它们的等效泛型接口。使用泛型集合类可以提供更高的类型安全性,在某些情况下还可以提供更好的性能,尤其是在存储值类型时,这些优势会体现得更明显。有关更多信息,请参见泛型的优点。

如果将紧密相关的数据组合到一个集合中,则能够更有效地处理这些紧密相关的数据。代替编写不同的代码来处理每一单独的对象,您可以使用相同的调用代码来处理一个集合的所有元素。

若要管理集合,可使用 Array 类和 System.Collections 类添加、移除和修改该集合中的个别元素或某一范围内的元素。甚至可以将整个集合复制到另一个集合中。某些 Collections 类具有排序功能并且大多数都有索引。自动处理内存管理,集合的容量会根据需要扩展。当访问集合成员时同步提供线程安全。某些 Collections 类可以生成包装,这些包装令集合是只读的或固定大小的。任何 Collections 类都可以生成自己的枚举数,该枚举数简化了对元素的循环访问。

在 .NET Framework 2.0 版中,泛型集合类提供了新功能,并且使得创建强类型集合变得容易。请参见 System.Collections.Generic 和 System.Collections.ObjectModel 命名空间。

【2.2】集合数据契约:

集合有如此强大的特性,这也是我们使用的一个重要原因。

【3】示例代码分析:

下面我们来介绍一下使用Dataset、 Datatable和集合类来传递数据的程序开发过程。依次介绍服务契约、宿主、客户端的开发配置过程,另外服务端设计了一个数据库,添加了部分演示数据,目的是方便Demo。

【3.1】服务契约:

服务契约定义了3个操作契约,分别是使用Dataset、Datatable、List来传递数据,WCF服务类实现了接口定义的操作契约,分别返回不同的数据结构类型。具体代码如下:

//ServiceContract 属性以及 Indigo 使用的所有其他属性均在 System.ServiceModel 命名空间中定义,
//因此本例开头使用 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;}
}

【3.2】托管宿主:

托管宿主的配置过程与前几节宿主类似,这里不在详述,配置文件里契约和MEX原数据节点一定要配置,具体代码如下:

<services><service behaviorConfiguration="WCFService.WCFServiceBehavior" name="WCFService.WCFService"><endpointaddress="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>

【3.4】客户端:

宿主配置完毕,编译运行宿主程序,我们在客户端添加服务的引用,输入正确的元数据交换地址,查询服务,可以看到如下的操作查询结果,如图:

我们可以看到客户端反序列化的本地类的信息。DataTable和DataSet使用的依然是.NET 类库的类型。对应的代理服务操作如下:

public System.Data.DataTable GetDataByTable() {return base.Channel.GetDataByTable();}public System.Data.DataSet GetDataByDataSet() {return base.Channel.GetDataByDataSet();}

但是我们定义的集合操作在反序列化为客户端操作以后以及发生了变化,客户单使用数组代替了我们的集合List.代码如下:

     public User[] GetDataByCollection() {             return base.Channel.GetDataByCollection();         }

WCF为集合类型提供了专属的封送机制,客户端发序列化的本地操作使用与之对应的数组。

【4】运行结果:

这里客户端使用了WinForm界面,借助DataGridView控件来显示数据,方便DEMO。分别绑定事件方法,通过客户端服务代理,调用WCF操作服务,获取数据。代码如下:

//Get data using DataTable By WCF proxyprivate 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 proxyprivate 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];//绑定数据源到控件
            }}

点击按钮,分别测试调用服务操作返回数据是否成功,运行结果如图:

【5】总结:

我们来看看使用这些类型进行数据传递的优点:

(1)在WCF中,还可以使用DataTable和DataSet的类型或者继承之数据集或者数据表。  对于WCF的客户端与服务而言,可以通过开发工具Visual Studio工具使用DataSet、DataTable以及它们的类型安全的派生对象进行数据的传输。

(2)在服务契约中使用数据表或者数据集还存在一个缺陷,那就是它可能暴露内部数据库表的数据结构。

(3)WCF为集合类型提供了专属的封送机制,客户端发序列化的本地操作使用与之对应的数组。.NET为集合类封装了丰富特性和操作,这也是我们使用的主要原因。

它们同样也有缺点,这个是我们必须注意的:

(1)如果全部是基于.net平台进行数据交换,比较方便,但是异构平台来说,这种方式过于繁琐。而且,这些数据访问类型都是特定的.NET类型。在序列化时,它们生成的数据契约样式也过于复杂,很难与其它平台进行交互;

(2)WCF主要的目标是面向服务,平台无关。但客户端必须知道ADO.NET关于此类的定义信息,,这些显然违背了面向服务的编程原则。

(3)使用序列化机制而不是WCF面向服务的数据契约特性,将来对数据库样式的修改会影响到客户端。虽然在应用程序内部可以传递数据表,但如果是跨越应用程序或公有的服务边界发送数据表。使用数组返回数据,代替DataTable和DataSet。

以上就是本节的全部内容,下面上传本节的示例代码供大家参考,/Files/frank_xl/WCFServiceDataSetFrankXuLei.rar。(大家有好的博客写作的经验,请赐教~我出现好几次写的文章保存失败,丢失的情况了。live writer怎么样?)

参考资料:

1.《DataSet》,http://baike.baidu.com/view/624618.html;

2.《DataSet类》,http://msdn.microsoft.com/zh-cn/library/system.data.dataset(VS.80).aspx

3.《集合和数据结构》,http://msdn.microsoft.com/zh-cn/library/7y3x785f(VS.80).aspx 4.《Programming in WCF Service》

转载于:https://www.cnblogs.com/wait-fly/p/4834389.html

使用数据集(DataSet)、数据表(DataTable)、集合(Collection)传递数据相关推荐

  1. mysql数据库视图重命名_数据表和视图:修改数据表

    在MySQL中,ALTER 语句用来修改数据表名称或者数据表字段名称.也可以用来添加或者删除数据表字段. ALTER 语句经常和"ADD", "DROP" an ...

  2. navicat mysql 建表语句_Navicat for MySQL怎么/如何创建数据表?Navicat for MySQL创建数据表教程_斗蟹游戏网...

    [斗蟹攻略]Navicat for MySQL是针对MySQL数据库管理而研发的管理工具,创建数据表是其最基本操作,下面就由斗蟹小编介绍Navicat for MySQL创建数据表的方法. Navic ...

  3. mysql 字段写入_MySQL为数据表的指定字段插入数据

    username not null 没有默认值/有默认值   insert不插入username字段 均不报错 2014年07月23日21:05    百科369 MySQL为数据表的指定字段插入数据 ...

  4. 【UE4】纯蓝图实现数据表(DataTable)的写入存储

    前言   UE4可以方便的实现表格的读取,通常是将csv表格文件按对应表头结构体导入后,作为引擎内的DataTable类型文件再进行使用.读取DataTable的操作,可以通过GetDataTable ...

  5. pythonpandas用sql查询数据表_pandas从数据库读取数据

    因为本周有一个是需要使用pandos做一个数据分析的需求,所以在这里做一下记录. Python中用Pandas进行数据分析,最常用的就是Dataframe数据结构, 这里我们主要介绍Pandas如何读 ...

  6. DataGrip 2019.2.5 —— MySQL数据表迁移到SQL Server数据表解决方案

    问题描述 DataGrip 2019.2.5中导出的MySQL数据库的数据表不能直接迁移到SQL Server数据库的数据表. 系统环境 DataGrip 2019.2.5 MySQL 8.0 SQL ...

  7. myisam数据表根据frm文件恢复数据表

    有时,我们重装mysql时,可能忘记备份数据了, 只留下了之前的mysql下面的data文件夹里的数据, 这时我们应该如何去恢复数据表呢 如果直接将原来的data目录导进现在的mysql,肯定是不行的 ...

  8. mysql数据表添加数值_MySQL中数据表和数据的操作

    一.数据库表的操作 1.数据表的创建 mysql> create tablet_user(-> id int unsigned not null auto_increment primar ...

  9. JavaWeb项目监听数据表变化并通知前台(数据来源于自身)

    最近公司有些项目中需要java程序去监听数据表,当数据有变化时把新数据通知前台并且展示出来.本人也去百度上查询了好多相关知识(本意是有现成抄的就直接抄,哈哈,但无奈没有),然后根据自己的理解写了个de ...

  10. Excel在数据表中悬停鼠标显示数据值

    打开一个实例文档,鼠标移动到数据表中,在柱状图上中悬停鼠标,可以看到没有显示数据的值. 鼠标单击左上角的<文件>按钮. 然后单击<选项>按钮. 在弹出的excel选项对话框中单 ...

最新文章

  1. python面试-Python面试题总结
  2. .NET泛型解析(上)
  3. 怎样使用element-starter快速搭建ElementUI项目
  4. SAP OData错误消息:Invalid format (return structure): Property Name ‘Guid‘, Property Value ‘000000
  5. 工作总结6:token问题
  6. 专访百度集团副总裁袁佛玉:科技创新对普惠金融正在充分发挥“乘数效应”
  7. PostgreSQL主备切换
  8. 清华大学计算机系网络课程视屏,清华大学计算机系网络课程
  9. Windows使用快捷键
  10. 应该根据哪些判断云服务器的好坏
  11. 腾讯的星星海服务器芯片,腾讯云星星海重磅发布两款自研新品 打造软硬一体云计算基础设施...
  12. 教学概述+教学内容+教学原则+教学方法+教学组织...+教学模式和教学策略
  13. UE4 令Actor对象在Editor下执行Tick
  14. 题解_UVA_11134_Fabled Rooks
  15. MathType6.9安装后,office16打开报错(DLL找不到)的解决方法
  16. 神奇的伊娃(eval),魔鬼的伊娃(eval)
  17. 2021最新 阿里云PostgreSQL案例精选2 - 图像识别、人脸识别、相似特征检索、相似人群圈选
  18. 【Rust日报】 2019-07-29:关于创建「更小的」Rust的思考
  19. latex 插图位置跑在文档最后的解决方法
  20. Python科研绘图第一期——线型图(Line)、条型图(Bar)、散点图(Scatter)、子图(subplot)

热门文章

  1. python求解括号匹配的相关问题
  2. linux 手动 创建数据库连接,Linux下手动创建Oracle数据库过程
  3. JavaScript语法学习
  4. C++ std::condition_variable wait() wait_for() 区别 怎么用 实例
  5. java并发编程(6)--CAS会导致“ABA问题“ 解决方案
  6. Linux ubuntu基本知识
  7. 区块链 p2p点对点网络是什么
  8. FISCO BCOS Solidity 智能合约Compiler error:Stack too deep, try removing local variables 如何传递超过16个参数变量
  9. 基于SSM的选课系统
  10. 信息处理工具计算机.ppt,第二课_计算机信息处理工具讲述.ppt