数据绑定
所有这三个对象都可以作为数据绑定控件的数据源。而DataSet 和 DataTable 可作为更广范围控件的数据源。这是因为DataSet 和 DataTable 实现了(生成Ilist接口)IlistSource接口,而SqlDataReader 实现了Ienumerable接口。许多能进行数据绑定的WinForm控件需要实现了Ilist接口的数据源。
这种不同是因为为每种对象类型设计的场景类型不同。DataSet (它包含 DataTable)是一个丰富的、非链接结构,它适合于Web和桌面(WinForm)应用程序。另一方面,数据阅读器已经为Web应用程序进行了优化,这种应用程序需要优化的、只能向前的数据访问。
检查将要绑定到的特定控件类型的数据源需求。
在应用程序层间传递数据
DataSet提供了可作为XML被任意操纵数据的关系图,并允许数据的非链接缓存拷贝在应用程序层与组件间传递。然而,SqlDataReader提供了更优化的性能,因为它避免了与创建DataSet相关的性能及内存开销。记住,DataSet对象的创建将导致多个子对象--包括DataTable, DataRow 和DataColumn--及作为这些子对象容器的集合对象的创建。
使用DataSet
使用SqlDataAdapter填充的DataSet对象,当:
你需要非链接的驻留内存的缓存数据,以便你能将它传递到其它组件或应用程序中的其它层。
你需要内存中的数据关系图以执行XML或非XML操作。
你正在使用的数据来自多个数据源,如多个数据库、表或文件。
你希望更新获得的一些或所有行,并希望利用SqlDataAdapter的批更新功能。
你要对控件绑定数据,而此控件需要支持IList接口的数据源。
更多信息
如果使用SqlDataAdapter生成DataSet 或 DataTable,需注意:
不必明确打开或关闭数据库链接。SqlDataAdapter Fill方法打开数据库链接,并在此方法返回前关闭该链接。如果链接原来已经打开,那么此方法仍使链接处于打开状态。
如果出于其它目的需要链接,那么考虑在调用Fill方法前打开链接。这样你就可以避免不必要的打开/关闭操作,提高性能。
尽管能重复使用同一SqlCommand对象多执行同样的命令,但不要重复使用此对象执行不同的命令。
关于如何利用SqlDataAdapter对象填充DataSet 或 DataTable对象的代码示例,见附录中的如何利用SqlDataAdapter 对象获得多行。
使用SqlDataReader
些劣情况,可以使用通过调用 SqlCommand 对象的ExecuteReader方法得到的SqlDataReader对象:
正在处理大量数据时--太多了而不能在单个缓冲区内维护。
希望减少应用程序在内存中的印迹。
希望避免与DataSet对象创建相关的开销。
希望对某控件执行数据绑定操作,而此控件支持实现了IEnumerable接口的数据源。
希望流水线化数据访问,并对其优化。
正在读取包含二进制大对象(BLOB)列的行。你可以使用SqlDataReader对象以可管理的大块为单位从数据库中将BLOB数据拉出来,而不是一次性地将所有数据提取出来。关于处理BLOB数据的更多细节,见本文处理BLOBs 一节。
更多信息
如果使用SqlDataReader对象,请注意:
在数据阅读器活动期间,底层的数据库链接保持打开,并不能用于其它任何目的。尽可能早地对SqlDataReader对象调用Close方法。
每个链接只能有一个数据阅读器。
通过向ExecuteReader方法传递CommandBehavior.CloseConnection枚举值,可以在使用完数据阅读器后,明确地关闭链接;或者,将链接生命周期绑定到SqlDataReader对象。这预示着当SqlDataReader对象关闭时,链接也将关闭。
在利用阅读器访问数据时,如果你知道列的底层数据类型,那么就应使用类型化存取器方法(如GetInt32 和 GetString),这是因为在读取列数据时,这些方法减少了读取列数据所需的类型转换量。
为避免将不必要的数据从服务器发送到客户端,如果你要关闭阅读器并抛弃所有保留的结果,那么在对阅读器调用Close方法前调用命令对象的Cancel方法。Cancel方法确保了服务器的结果被抛弃,而不会被发送到客户端。相反,对数据阅读器调用Close方法会使阅读器不必要地提取出保留的结果,以清空数据流。
如果要得到从存储过程返回的输出值或返回值,并且你在利用SqlCommand对象的ExecuteReader方法,那么在得到输出或返回值前,必须对阅读器调用Close方法。
关于演示如何利用SqlDataReader对象的代码示例,附录中的如何利用SqlDataReader对象获取多行数据。
使用XmlReader
下列情况下,使用通过调用SqlCommand对象的ExecuteXmlReader方法得到的XmlReader对象:
希望将得到的数据作为XML 处理,但不希望引发因创建DataSet对象而造成的额外性能开销,并且不需要数据的非链接缓存。
希望利用SQL Server FOR XML 语法的功能,这种语法允许以灵活的方式从数据库中得到XML片段(即,不带根元素的XML文档)。例如,这种方法使你能够精确指定元素名,是使用元素还是使用以属性为核心的图解,图解是否随XML数据一起被返回,等等。
更多信息
如果使用XmlReader,请注意:
在从XmlReader对象中读取数据时,链接必须保持打开。SqlCommand对象的 ExecuteXmlReader方法目前不支持CommandBehavior.CloseConnection枚举值,因此在使用完阅读器后必须明确关闭链接。
对于如何使用XmlReader对象的代码示例,见附录中的如何利用 XmlReader获取多行数据。
获取单行数据
在这种场景中,将从数据源中获取包含一组指定列的单行数据。例如,你得到一个客户ID,并希望查找与客户相关的细节;或得到一个产品ID,并希望得到产品信息。
方法比较
如果要对从数据源中得到的一行数据执行绑定操作,可以用SqlDataAdapter对象填充DataSet 或DataTable对象,其方式与在先前讨论过的获取多行数据及重复场景中描述的方式相同。然而,除非特别需要DataSet 或DataTable对象的功能,否则应当避免创建这些对象。
如果需要获取单行数据,那么请使用下面的一种方法:
使用存储过程输出参数.
使用SqlDataReader对象.
这两种方法都避免了在服务器端创建结果集,在客户端创建DataSet对象的不必要额外开销。每种方法的相对性能要依赖于强度等级及数据库链接池化是否被使能。当数据库链接池化使能时,性能测试表明存储过程方法在高强度环境下(同时存在200多链接)其性能比SqlDataReader方法高近30%。
使用存储过程输出参数
如下情况中使用存储过程输出参数:
要从链接池化使能的多层Web应用程序中获得一行数据。
更多信息
关于演示如何使用存储过程输出参数的代码示例,见附录中的使用存储过程输出参数获取一行数据。
使用SqlDataReader对象
下列情况,需使用SqlDataReader对象:
除了数据值,还需要元数据时。可以利用数据阅读器的GetSchemaTable方法获取列元数据。
未使用链接池化时。在链接池化无效时,SqlDataReader对象在所有强度环境下都是好方式;性能测试表明,在200浏览器链接时,此方法比存储过程方法在性能上要高约20%。
更多信息
如果知道查询结果只需返回一行,那么在调用SqlCommand对象的ExecuteReader 方法时,使用CommandBehavior.SingleRow枚举值。一些供应器,如OLE DB .NET数据供应器,用此技巧来优化性能。例如,供应器使用IRow接口(如果此接口存在)而不是代价更高的IRowset接口。这个参数对SQL Server .NET数据供应器没有影响。
在使用SqlDataReader对象时,总是应当通过SqlDataReader对象的类型化存取器方法,如GetString 和GetDecimal,获得输出参数。这样做就避免了不必要的类型转换。
关于如何使用SqlDataReader对