SqlDataAdapter与SqlDataReader

ste*_*sha 125 .net c#

使用SqlDataAdapter和SqlDataReader从数据库获取数据有什么区别?

我特别关注他们的优点和缺点,以及他们的速度和记忆表现.

谢谢

Joe*_*orn 189

SqlDataReader的:

  • 保持连接打开直到完成(不要忘记关闭它!).
  • 通常只能迭代一次
  • 对更新回数据库没那么有用

另一方面,它:

  • 一次只在内存中有一条记录而不是整个结果集(这可能很大)
  • 这个迭代的速度和你一样快
  • 允许您更快地开始处理结果(一旦第一条记录可用)

SqlDataAdapter的/数据集

  • 允许您在加载数据后立即关闭连接,甚至可以自动关闭它
  • 所有结果都可以在内存中找到
  • 您可以根据需要多次迭代它,甚至可以按索引查找特定记录
  • 有一些内置的功能可以更新回数据库

代价是:

  • 很多更高的内存使用
  • 等到所有数据都加载后再使用它们

所以它真的取决于你正在做什么,但我倾向于更喜欢DataReader,直到我需要一些只受数据集支持的东西.SqlDataReader非常适合绑定到只读网格的常见数据访问情况.

有关详细信息,请参阅Microsoft官方文档.

  • 这个答案有误导性.如果用"using"语句包装SqlConnection和SqlDataReader对象(无论如何,因为它们是IDisposable),连接将自动关闭.您可以将DataSet与SqlDataReader一起使用:只需调用DataSet.Load(SqlDataReader). (7认同)
  • @Cdaragorn MSDN文档通常非常清楚Close()与Dispose().例如,在SqlConnection的情况下,文档说Close()和Dispose()在功能上是等价的.我没有反对调用Close(),但对所有IDisposable也应该调用Dispose() - 最简单的方法是使用using语句.如果你知道Dispose()没有调用Close(),那么你应该在finally块中调用Close(),而不是在using块中(所以如果有异常,它仍会被调用). (5认同)
  • DataSet是内存中的数据存储区,而datareader只是检索数据的媒介.更轻松的说明,您可以在DataSet上运行Linq查询,但不能在datareader上运行. (4认同)
  • @RickNZ不要太快信任使用语句为你关闭事物.他们调用对象的Dispose()方法,而不是它的Close()方法,并且我遇到了至少一个Dispose没有为我实际关闭对象的情况.最好在using块中包含对close方法的显式调用. (4认同)

jay*_*won 18

答案可能相当广泛.

从本质上讲,我通常会影响我决定使用哪个的主要区别在于,使用SQLDataReader,您将从数据库中"流式传输"数据.使用SQLDataAdapter,您将数据从数据库中提取到一个对象中,该对象本身可以进一步查询,以及执行CRUD操作.

显然,SQLDataReader的数据流速度要快得多,但一次只能处理一条记录.使用SQLDataAdapter,您可以从数据库中获得与查询匹配的行的完整集合,以使用/传递代码.

警告:如果您使用的是SQLDataReader,请始终始终确保编写正确的代码以关闭连接,因为您使用SQLDataReader保持连接打开.如果不这样做,或适当的错误处理,关闭的情况下,错误的处理结果将在连接跛子用连接泄漏您的应用程序.

请原谅我的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     
Run Code Online (Sandbox Code Playgroud)

等价的C#:

using (var cn = new SqlConnection("..."))
using (var cmd = new SqlCommand("..."))
{
    cn.Open();
    using(var rdr = cmd.ExecuteReader())
    {
        while(rdr.Read())
        {
            //...
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 如果您的目标是使用 db 上的选择查询获取数据,并且仅在不同行访问此数据,转到上一行等,那么您可以使用 SQLDatareader 并使用 dtable.Load(rdr) 将其加载到数据表中。然后在此数据表中上下浏览。您可以使用此方法代替 DataAdapter... (2认同)

Wim*_*dse 13

SqlDataAdapter通常用于填充DataSet或DataTable,因此您可以在连接关闭(断开连接访问)后访问数据.

SqlDataReader是一个快速前向连接的游标,通常比填充DataSet/DataTable更快.

此外,使用SqlDataReader,您一次处理一条记录的数据,并且不在内存中保存任何数据.显然,使用DataTable或DataSet,您确实有内存分配开销.

如果您不需要将数据保存在内存中,那么只需要渲染内容,请转到SqlDataReader.如果要以断开连接的方式处理数据,请选择DataAdapter以填充DataSet或DataTable.


Ada*_*Dev 10

想要从数据库填充内存中的DataSet/DataTable时,请使用SqlDataAdapter.然后,您可以灵活地关闭/释放连接,在内存中传递数据表/集.然后,您可以使用数据适配器与InsertCommand/UpdateCommand一起操作数据并将其保留回数据库.

想要快速,低内存的数据访问时使用SqlDataReader,而无需灵活地例如在业务逻辑中传递数据.这对于大数据量的快速,低内存使用检索更为理想,因为它不会一次性将所有数据加载到内存中 - 使用SqlDataAdapter方法,DataSet/DataTable将填充所有数据,因此如果有很多行和列,需要大量的内存才能容纳.