【问题标题】:Where are the data loaded?数据加载在哪里?
【发布时间】:2018-11-02 09:36:37
【问题描述】:

我注意到很多人不了解如何执行查询以从数据库中检索数据。

通常有如下代码:

var reader = await sqlCommand.ExecuteReaderAsync();
dataTable.Load(reader);

* 上有几个答案,将其显示为将数据异步下载到DataTable

不过,我相信ExecuteReader 方法不会加载数据,而只会创建读取器的实例。

我可以通过官方documentation 的引用来确认这一点:

DataReader 提供无缓冲的数据流,允许 有效处理来自数据源的结果的过程逻辑 依次。检索时,DataReader 是一个不错的选择 大量数据,因为数据没有缓存在内存中。

与我发生争执的一个人引用了link 并声称数据下载正在那里进行。但是我没有在这段代码中看到对 Read 方法的调用!同时,下面的ExecuteScalarAsync方法也有这样的调用。

因此数据将使用DataTable.Load 方法加载或使用while(reader.Read()) 循环完成。我说的对吗?

那么数据加载在哪里:ExecuteReader(Async) 方法还是Read/Load 方法?

【问题讨论】:

  • 是的,我知道我的问题的正确答案。但我希望得到社区的确认,以便稍后在类似的争议中引用它。
  • SO 并不是真正解决与同事纠纷的地方;尤其是当答案很明显并且可以通过几行代码轻松验证时。来自文档: ExecuteReaderAsync() ExecuteReader() 的异步版本,它将 CommandText 发送到 Connection 并构建 SqlDataReader。你是对的。
  • ReadAsync() :Read() 的异步版本,它将读取器推进到结果集中的下一条记录。 T
  • 如果您想要一个可靠的答案,可能有必要提供赏金(一旦该选项可用)。必须做同样的事情才能在这里得到我的问题的可靠答案:*.com/questions/49899012/…
  • @MitchWheat - 完全同意。但是 SO 有不正确的答案(接受和赞成),我无法说服作者修复它们。

标签: c# sql .net database ado.net


【解决方案1】:

何时实际检索数据是一个棘手的问题,因为您使用的是 DataReader。

DataReaders 的核心工作类似于Enumerators。 Read() 所做的事情与Current 相当(Current 是一个属性,所以它是一个函数调用,看起来不像一个)。在这两种情况下,我都无法告诉您数据何时传输/已完全构建在内存中。那是一个实现细节。我可以告诉你,当 Read/Current 返回它的“我已完成”返回值而不是下一个结果时,它已被完全检索。

如果我从一个数组构建一个枚举器,那么所有数据都已经存在于内存中。而且,这种情况并不少见,每次调用 foreach 循环时都会发生这种情况! Foreach 不适用于集合,只能用于枚举器。幸运的是,从一个 cllection 中获取 Enumerator 非常简单,它是一个隐式转换。

另一方面,枚举器可能是从外部数据源构建的。喜欢Directory.EnumerateFiles()File.ReadLines()。最新,下一行在调用 Current 时立即加载。但是,如果代码编写者有点聪明,那么下一个 1-many 结果将在 Current 调用之间在后台加载。它提前加载了多少,甚至可能取决于环境(你必须为此浪费多少内存)。如果调用 Current 时 hte 数据已经存在,则返回。如果不是,Current 将成为阻塞调用,直到实际检索到下一个结果。

【讨论】:

  • 这里专门从RDBMS获取数据。
  • @AlexanderPetrov:正如我所说,拥有 DB 的读者通常像 Enumerators 一样工作。如果“请下一个条目”功能返回“没有更多条目”,我知道数据传输已完成。但是在“提前加载所有数据”和“在调用“请下一个条目”的那一刻只获取一个项目之间,一切皆有可能。即使使用相同的代码。
最近更新 更多