【发布时间】:2009-11-04 21:30:06
【问题描述】:
使用 SqlDataAdapter 与 SqlDataReader 从数据库获取数据有什么区别?
我正在专门研究它们的优缺点以及它们的速度和内存性能。
谢谢
【问题讨论】:
使用 SqlDataAdapter 与 SqlDataReader 从数据库获取数据有什么区别?
我正在专门研究它们的优缺点以及它们的速度和内存性能。
谢谢
【问题讨论】:
另一方面,它:
代价是:
所以这真的取决于你在做什么,但我倾向于更喜欢 DataReader,直到我需要仅由数据集支持的东西。 SqlDataReader 非常适合绑定到只读网格的常见数据访问案例。
有关详细信息,请参阅the official Microsoft documentation。
【讨论】:
while (reader.Read()) 循环中将 DataReader 强制转换为 IDataRecord 即可。
这个问题的答案可能相当广泛。
本质上,对我而言,通常会影响我使用哪个决定的主要区别在于,使用 SQLDataReader,您可以从数据库中“流式传输”数据。使用 SQLDataAdapter,您可以将数据库中的数据提取到一个对象中,该对象本身可以进一步查询,并对其执行 CRUD 操作。
显然,对于数据流,SQLDataReader 的速度要快得多,但您一次只能处理一条记录。使用 SQLDataAdapter,您可以从数据库中获得与查询匹配的行的完整集合,以使用/传递您的代码。
警告:如果您使用的是 SQLDataReader,请始终、始终、始终确保编写正确的代码来关闭连接,因为您使用 SQLDataReader 保持连接打开。如果不这样做,或在处理结果时发生错误时关闭连接的正确错误处理将CRIPPLE您的应用程序连接泄漏。
请原谅我的 VB,但这是您在使用 SqlDataReader 时应该拥有的最少代码量:
Using cn As New SqlConnection("..."), _
cmd As New SqlCommand("...", cn)
cn.Open()
Using rdr As SqlDataReader = cmd.ExecuteReader()
While rdr.Read()
''# ...
End While
End Using
End Using
等效的 C#:
using (var cn = new SqlConnection("..."))
using (var cmd = new SqlCommand("..."))
{
cn.Open();
using(var rdr = cmd.ExecuteReader())
{
while(rdr.Read())
{
//...
}
}
}
【讨论】:
SqlDataAdapter 通常用于填充 DataSet 或 DataTable,因此您可以在连接关闭后访问数据(断开访问)。
SqlDataReader 是一个快速只进且连接的游标,通常比填充 DataSet/DataTable 更快。
此外,使用 SqlDataReader,您可以一次处理一条数据,并且不会在内存中保存任何数据。显然,对于 DataTable 或 DataSet,您确实有内存分配开销。
如果您不需要将数据保存在内存中,那么仅用于渲染内容,请使用 SqlDataReader。如果您想以断开连接的方式处理数据,请选择 DataAdapter 来填充 DataSet 或 DataTable。
【讨论】:
想要从数据库中填充内存中的 DataSet/DataTable 时,请使用 SqlDataAdapter。然后,您可以灵活地关闭/处理连接,在内存中传递数据表/集。然后,您可以使用数据适配器以及 InsertCommand/UpdateCommand 操作数据并将其持久化回 DB。
当需要快速、低内存占用的数据访问而不需要灵活性时使用 SqlDataReader,例如围绕业务逻辑传递数据。这对于大数据量的快速、低内存使用检索更为优化,因为它不会一次性将所有数据加载到内存中 - 使用 SqlDataAdapter 方法,DataSet/DataTable 将填充所有数据,所以如果有很多行和列,需要大量内存来保存。
【讨论】:
Fill 函数在内部使用 DataReader。如果您的考虑是“哪个更有效?”,那么在逐条记录填充集合的紧密循环中使用 DataReader 可能与使用 DataAdapter.Fill 对系统的负载相同。
(System.Data.dll、System.Data.Common.DbDataAdapter、FillInternal。)
【讨论】: