论文部分内容阅读
摘要: 就MicrosoftADO.NET应用程序中DataSet和DataReader对象实现和获得最佳性能、可伸缩性以及功能的最佳解决方案进行研究;同时也就DataSet或DataReader的最佳时机、如何优化访问它们所包含数据、以及如何优化使用DataAdapter和DataView的技巧进行深入的研究。
关键词: DataSet;DataReader;最佳性能;DataAdapter
中图分类号:TP3文献标识码:A文章编号:1671-7597(2011)0110167-01
0 引言
ADO.NET是一组包括在.NET框架中的库,用于在.NET应用程序的各种数据存储之间通信。ADO.NET库中包含了可与数据源连接、提交查询并处理结果的类。还可将ADO.NET作为一种强壮、层次化的、断开连接的数据缓存来使用,以脱机处理数据。最主要的断开连接对象数据集可执行对数据进行排序、搜索、筛选、存储挂起更改,并在层次化数据中进行浏览操作。
ADO.NET为我们提供了两个对象,用于检索关系数据并将其存储在内存中:DataSet和DataReader。DataSet提供一个内存中数据的关系表示形式,一整套包括一些表在内的数据(这些表包含数据、对数据进行排序并约束数据),以及表之间的关系。DataReader提供一个来自数据库的快速、只进、只读数据流。
1 DataSet与DataReader对象使用情况的分析
当设计应用程序时,要考虑应用程序所需功能的等级,从而来确定使用DataSet还是DataReader。
1.1 使用DataSet对象的情况例举
1)在结果的多个离散表之间进行导航。
2)操作来自多个数据源(例如,来自多个数据库、一个XML文件和一个电子表格的混合数据)的数据。
3)在各层之间交换数据或使用XMLWeb服务。与DataReader不同的是,DataSet能传递给远程客户端。
4)重用同样的行组,以便通过缓存获得性能改善(例如排序、搜索或筛选数据)。
5)每行执行大量处理。对使用DataReader返回的每一行进行扩展处理会延长服务于DataReader的连接的必要时间,这影响了性能。
6)使用XML操作对数据进行操作,例如可扩展样式表语言转换(XSLT
转换)或XPath查询。
1.2 对使用DataReader对象情况例举
1)不需要缓存数据。
2)要处理的结果集太大,内存中放不下。
3)需要以只进、只读方式快速访问数据。
因此,使用DataAdapter取代DataSet提升的性能表现为节省了DataSet占用内存和填充DataSet需要的循环。一般来说,此性能提升只是象征性的,因此,设计决策应以所需功能为基础。
2 dataset对象的使用与优化
2.1 刷新DataSet中的数据
如果想用服务器上的更新值刷新DataSet中的值,就使用DataAdapter.
Fill。如果有在DataTable上定义的主键,DataAdapter.Fill会根据主键进行新行匹配,并且当更改到现有行时应用服务器上的值。即使刷新之前修改了它们,刷新行的RowState仍被设置为Unchanged。如果没有为Data
Table定主键,DataAdapter.Fill就用可能重复的主键值添加新行。
如果想用来自服务器的当前值刷新表,并同时保留对表中的行所做的任何更改,必须首先用DataAdapter.Fill填充表,并填充一个新的DataTable,然后用preserveChanges值true把DataTableMerge到DataSet中。
2.2 在DataSet中搜索数据
在DataSet中查询与特定条件相匹配的行时,可以利用基于索引的查找提高搜索性能。当把PrimaryKey值赋给DataTable时,会创建一个索引。当给DataTable创建DataView时,也会创建一个索引。下面是一些利用基于索引进行查找的技巧。
1)对于涉及到非主键列的查询,可以使用DataView为数据的多个查询提高性能。当把排序顺序应用到DataView时,就会建立一个搜索时使用的索引。DataView公开Find和FindRows方法,以便查询基础DataTable中的数据。
2)如果不需要表的排序视图,仍可以通过为DataTable创建DataView
来利用基于索引的查找。只有对数据执行多个查询操作时,这样才会带来好处。如果只执行单一查询,创建索引所需要的处理就会降低使用索引所带来的性能提升。
2.3 用多个表填充DataSet
如果使用批处理SQL语句检索多个表并填充DataSet,第一个表用指定给Fill方法的表名命名。后面的表用指定给Fill方法的表名加上一个从1开始并且增量为1的数字命名。
3 DataReader对象的使用与优化
1)一些关闭对象的情况分析。完成读数据之后总是要关闭DataReader。如果使用Connection只是用于返回DataReader,那么关闭DataReader之后立刻关闭它。
另外一个关闭方法是把CommandBehavior.CloseConnection传递给ExecuteReader方法,以确保相关的连接在关闭DataReader时被关闭。如果从一个方法返回DataReader,而且不能控制DataReader或相关连接的关闭,则这样做特别有用。
2)默认情况下,DataReader每次Read时都要把整行加载到内存。这允许在当前行内随机访问列。如果不需要这种随机访问,为了提高性能,就把CommandBehavior.SequentialAccess传递给ExecuteReader调用。这将DataReader的默认行为更改为仅在请求时将数据加载到内存。注意,CommandBehavior.SequentialAccess要求顺序访问返回的列。也就是说,一旦读过返回的列,就不能再读它的值了。
3)如果已经完成读取来自DataReader的数据,但仍然有大量挂起的未读结果,就在调用DataReader的Close之前先调用Command的Cancel。调用DataReader的Close会导致在关闭游标之前检索挂起的结果并清空流。调用Command的Cancel会放弃服务器上的结果,这样,DataReader在关闭的时候就不必读这些结果。如果要从Command返回输出参数,还要调用Cancel放弃它们。如果需要读取任何输出参数,不要调用Command的Cancel,只要调用DataReader的Close即可。
4 结束语
ADO.NET2.0提供了两个用于检索关系数据的对象:DataSet和Data
Reader,并且这两个对象都可以将检索的关系数据存储在内存中。在软件开发过程中经常用到这两个控件,虽然这两个控件在使用和功能方面的相似,但是这两个对象其各自的特点又决定了我们应该就数据的情况进行具体分析从而得出使用哪个对象更加合适。
关键词: DataSet;DataReader;最佳性能;DataAdapter
中图分类号:TP3文献标识码:A文章编号:1671-7597(2011)0110167-01
0 引言
ADO.NET是一组包括在.NET框架中的库,用于在.NET应用程序的各种数据存储之间通信。ADO.NET库中包含了可与数据源连接、提交查询并处理结果的类。还可将ADO.NET作为一种强壮、层次化的、断开连接的数据缓存来使用,以脱机处理数据。最主要的断开连接对象数据集可执行对数据进行排序、搜索、筛选、存储挂起更改,并在层次化数据中进行浏览操作。
ADO.NET为我们提供了两个对象,用于检索关系数据并将其存储在内存中:DataSet和DataReader。DataSet提供一个内存中数据的关系表示形式,一整套包括一些表在内的数据(这些表包含数据、对数据进行排序并约束数据),以及表之间的关系。DataReader提供一个来自数据库的快速、只进、只读数据流。
1 DataSet与DataReader对象使用情况的分析
当设计应用程序时,要考虑应用程序所需功能的等级,从而来确定使用DataSet还是DataReader。
1.1 使用DataSet对象的情况例举
1)在结果的多个离散表之间进行导航。
2)操作来自多个数据源(例如,来自多个数据库、一个XML文件和一个电子表格的混合数据)的数据。
3)在各层之间交换数据或使用XMLWeb服务。与DataReader不同的是,DataSet能传递给远程客户端。
4)重用同样的行组,以便通过缓存获得性能改善(例如排序、搜索或筛选数据)。
5)每行执行大量处理。对使用DataReader返回的每一行进行扩展处理会延长服务于DataReader的连接的必要时间,这影响了性能。
6)使用XML操作对数据进行操作,例如可扩展样式表语言转换(XSLT
转换)或XPath查询。
1.2 对使用DataReader对象情况例举
1)不需要缓存数据。
2)要处理的结果集太大,内存中放不下。
3)需要以只进、只读方式快速访问数据。
因此,使用DataAdapter取代DataSet提升的性能表现为节省了DataSet占用内存和填充DataSet需要的循环。一般来说,此性能提升只是象征性的,因此,设计决策应以所需功能为基础。
2 dataset对象的使用与优化
2.1 刷新DataSet中的数据
如果想用服务器上的更新值刷新DataSet中的值,就使用DataAdapter.
Fill。如果有在DataTable上定义的主键,DataAdapter.Fill会根据主键进行新行匹配,并且当更改到现有行时应用服务器上的值。即使刷新之前修改了它们,刷新行的RowState仍被设置为Unchanged。如果没有为Data
Table定主键,DataAdapter.Fill就用可能重复的主键值添加新行。
如果想用来自服务器的当前值刷新表,并同时保留对表中的行所做的任何更改,必须首先用DataAdapter.Fill填充表,并填充一个新的DataTable,然后用preserveChanges值true把DataTableMerge到DataSet中。
2.2 在DataSet中搜索数据
在DataSet中查询与特定条件相匹配的行时,可以利用基于索引的查找提高搜索性能。当把PrimaryKey值赋给DataTable时,会创建一个索引。当给DataTable创建DataView时,也会创建一个索引。下面是一些利用基于索引进行查找的技巧。
1)对于涉及到非主键列的查询,可以使用DataView为数据的多个查询提高性能。当把排序顺序应用到DataView时,就会建立一个搜索时使用的索引。DataView公开Find和FindRows方法,以便查询基础DataTable中的数据。
2)如果不需要表的排序视图,仍可以通过为DataTable创建DataView
来利用基于索引的查找。只有对数据执行多个查询操作时,这样才会带来好处。如果只执行单一查询,创建索引所需要的处理就会降低使用索引所带来的性能提升。
2.3 用多个表填充DataSet
如果使用批处理SQL语句检索多个表并填充DataSet,第一个表用指定给Fill方法的表名命名。后面的表用指定给Fill方法的表名加上一个从1开始并且增量为1的数字命名。
3 DataReader对象的使用与优化
1)一些关闭对象的情况分析。完成读数据之后总是要关闭DataReader。如果使用Connection只是用于返回DataReader,那么关闭DataReader之后立刻关闭它。
另外一个关闭方法是把CommandBehavior.CloseConnection传递给ExecuteReader方法,以确保相关的连接在关闭DataReader时被关闭。如果从一个方法返回DataReader,而且不能控制DataReader或相关连接的关闭,则这样做特别有用。
2)默认情况下,DataReader每次Read时都要把整行加载到内存。这允许在当前行内随机访问列。如果不需要这种随机访问,为了提高性能,就把CommandBehavior.SequentialAccess传递给ExecuteReader调用。这将DataReader的默认行为更改为仅在请求时将数据加载到内存。注意,CommandBehavior.SequentialAccess要求顺序访问返回的列。也就是说,一旦读过返回的列,就不能再读它的值了。
3)如果已经完成读取来自DataReader的数据,但仍然有大量挂起的未读结果,就在调用DataReader的Close之前先调用Command的Cancel。调用DataReader的Close会导致在关闭游标之前检索挂起的结果并清空流。调用Command的Cancel会放弃服务器上的结果,这样,DataReader在关闭的时候就不必读这些结果。如果要从Command返回输出参数,还要调用Cancel放弃它们。如果需要读取任何输出参数,不要调用Command的Cancel,只要调用DataReader的Close即可。
4 结束语
ADO.NET2.0提供了两个用于检索关系数据的对象:DataSet和Data
Reader,并且这两个对象都可以将检索的关系数据存储在内存中。在软件开发过程中经常用到这两个控件,虽然这两个控件在使用和功能方面的相似,但是这两个对象其各自的特点又决定了我们应该就数据的情况进行具体分析从而得出使用哪个对象更加合适。