ADO.NET 数据表与数据读取器
如果您只需要显示数据而不需要操作数据,则 DataReader 比 DataTable 更有效。但是,要从数据访问层获取 DataReader,我是否应该将连接对象保持打开状态?我觉得这也是一个非常大的效率问题。那么是否有另一种方法可以充分利用 DataReader?
The DataReader is more efficient than a DataTable if you only need to show data but not manipulate it. However, to get a DataReader from the data access layer should I leave the connection object open? I think this is also a very big efficiency problem. So is there another approach to this in order to take full advantage of the DataReader?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
是的,数据读取器绝对是最有效的 - 但您不想希望长时间保持连接打开!
DataReader
将数据读入实体对象;打开连接、读取数据、关闭连接这可能是您可以获得的最有效的方法 - 这是一些工作,一些无聊的代码等等,但它是尽可能快的。
如果您对开发人员的生产力比原始速度更感兴趣,为什么不使用某种 ORM 来完成所有这些无聊、烦人的来回映射呢?为您节省大量编码和维护的麻烦!
Yes, the data reader is definitely the most efficient - but you do not want to keep a connection open for a long period of time!
DataReader
to read your data into an entity object; open the connection, read the data, close the connectionThis is probably the most efficient you can get - it's a bit of work, some boring code, and all, but it's about as fast as it can be.
If you're more interested in developer productivity than raw speed, why not use some kind of an ORM to do all this boring, annoying mapping back and forth? Saves you a lot of coding and messy stuff to maintain!
我从来没有让 DataReader 暴露在外(脱离 DAL)。您在某处保持连接打开只是时间问题。另外,我几乎从未在一次调用中处理如此多的数据,而传递 DataTable 或 DataSet 会出现问题。
我们使用的是面向对象的语言,DAL 可以真正利用这一点。您的项目中应该只有一行代码来获取连接字符串。只有一个对象实际接触数据库(调用 ExecuteNonQuery、DA.Fill() 等)。
这还可以让您充分参与记录异常等工作,因为您只需执行一次。因此,在我用于所有项目中所有 DAL 对象的一个 DAL 基类中,我的逻辑是,如果 DAL 引发异常,则会将其记录到数据库中的表中。如果数据库日志记录失败,此日志记录将故障转移到文本文件。
由于我封装了所有这些,因此获取数据的代码现在看起来像:(
或更可能是 BAL 对象位于两者之间)。 DB 是一个普通对象(非静态),但每个应用程序仅实例化一次。
I never let a DataReader out into the wild (out of the DAL). Only a matter of time before you are leaving connections open somewhere. Also, I’m almost never dealing with so much data on a single call where passing around a DataTable or DataSet presents a problem.
We are using an object oriented language and the DAL can really take advantage of this. There should only be one line of code in your project that gets the connection string. Only one object that actually touches the database (calls ExecuteNonQuery, DA.Fill(), etc.)
This also lets you get pretty involved with logging exceptions, etc. because you are only doing it once. So in the one DAL base class that I use for all of my DAL object in all of my project I have the logic that if the DAL throws an exception then it is logged to a table in my database. This logging fails-over to a text file if the database logging fails.
Since I encapsulate all of this, my code to get the data now looks like:
(or more likely a BAL object sits between the 2). The DB is a normal object (not static), but it only instantiated once per application.
让您的数据层返回对象,而不是数据表或数据读取器。我建议您使用数据读取器填充对象。
Let your data layer return objects, not datatables or data readers. I would suggest you populate your objects using a data reader.
我通常做的是使用 CommandBehavior.CloseConnection 打开阅读器。然后我运行读取器并将数据读入我自己的对象模型或列表或内存中的任何数据,然后关闭读取器。它与数据表做了很多相同的事情,但我只是讨厌处理臃肿且松散类型的数据结构。
What I usually do is open the reader with CommandBehavior.CloseConnection. Then I run through the reader and read the data into my own object model or list or whatever in memory with the data and then close the reader. It does much of the same stuff as a data table, but I just hate dealing with bloated and loosely-typed data stuctures.
让我们有一个愚蠢的基准来检查 DataReader(.Net 版本 4)的速度有多快。
我从数据库 (SQL Server 2000) 中获取一条记录并读取其所有字段。我重复这个过程1000次。 DataReader 花费了 17.3327585 秒,DataTable 花费了 18.37320156 秒,因此对于 1000 次读取,DataReader 比 DataTable 快约 1.04 秒。
因此,如果 DataReader 优于 DataTable,则性能将提高 0.00104 秒。
看看 DataSet 比 DataReader 慢是因为……吗?
Let us have a silly benchmark to check how much faster the DataReader (.Net version 4) is.
I fetched one record from the database (SQL Server 2000) and read all its fields. I repeated this process 1000 times. DataReader took 17.3327585 seconds and DataTable took 18.37320156 and so DataReader is ~1.04 seconds faster than DataTable for 1000 reads.
So, one would get a performance gain of 0.00104 seconds if DataReader is preferred over DataTable.
Look at Is DataSet slower than DataReader due to…? as well
当我之前研究这个问题时,我相信我发现 DataReader 和 DataTable 之间的性能差异是微不足道的,除了可能非常大量的数据。从那时起,我通常使用 DataTable,因为它功能更齐全,可以断开连接等。
When I researched this before, I believe I discovered that the performance difference between DataReader and DataTable was trivial, except for perhaps very large amounts of data. Since then, I have typically used DataTable as it's more full-featured, can be worked with disconnected, etc.
如果您想完全抽象 ADO.NET 的连接和仪式,DataReader 是一个小挑战。我真的不喜欢我的数据工具有一个松散的开放连接,希望 DataReader 被释放(假设您使用了选项CommandBehavior.CloseConnection)。此外,当使用大量 DataReader 时,很难池化连接,因为在前一个 DataReader 关闭之前您无法对连接执行任何操作。它们不能轻易传递。您的数据工具不是真正的抽象。
另一方面,数据表非常灵活,可以编写一些非常高效、清晰的代码。 Linq-To-DataTable 很棒。幸运的是,DataTable 实际上相当高效。对于非大型结果集,它几乎与数据读取器一样快。 (当然,这取决于您正在做什么。)我越来越多地从我的数据工具而不是读者中获取数据表。它确实让生活变得简单。我可以继续使用同一个打开的连接。数据工具中没有“状态”。
获取 DataReader 的代码非常简单。因此,当我确实需要 DataReader(不经常)时,我只需让 DAL 向我提供连接,然后我自己获取 DataReader。
If you want to completely abstract the connections and ceremony of ADO.NET, the DataReader is a small challenge. I really don't like my data tool having an open connection on the loose, hoping the DataReader is disposed (assuming you used option CommandBehavior.CloseConnection). Also, when using a lot of DataReaders, it's difficult to pool connections, since you can't do anything with the connection until the previous DataReader is closed. They can't be passed around easily. Your Data-tool is not a true abstraction.
DataTables on the other hand are extremely flexible and can make for some very efficient, clear code. Linq-To-DataTable is great. Luckily the DataTable is actually pretty efficient. For non-huge result-sets it is almost as fast as the datareader. (it depends of course on exactly what you're doing.) More and more I am getting DataTables from my data-tool rather than Readers. It really makes life simple. I can continue to use the same open connection. There's no "state" in data-tool.
The code for getting a DataReader is very simple. So when I really do need a DataReader (not often), I just let my DAL hand me my connection and I get my DataReader myself.
直接来自文档:
虽然谈论
DataSet
基本上大部分内容也适用于DataTable
。从效率的角度来看,这是来自 msdn 本身的罕见基准测试。底线是 DataReader 稍微快一点,如果重要的话..也请参阅此相关问题,其中建议了一些很酷的 ORM 和基准测试。
Straight from the documentation:
Though talking about
DataSet
basically most of it holds forDataTable
too. From an efficiency standpoint, here is rare benchmarking from msdn itself. The bottom line isDataReader
is marginally faster, and if it matters..See this related question too which suggests some cool ORMs and benchmarking.
这与我在此处发布的内容相同。
我用各种方法自己做了一些基准测试:
1 和 2 返回 DataTable,而其余的强类型结果集,所以它完全不是苹果对苹果,但我同时相应地计时。
仅是要点:
查询返回大约 1200 行和 5 个字段(运行 100 次)。除了
Read1
之外,一切都表现良好。其中我更喜欢Read3
,它延迟返回数据,如枚举的。如果您只需要枚举它,这对记忆很有帮助。要在内存中保存集合的副本,最好根据需要使用Read4
或Read5
。This is the same as I posted here.
I did some benchmarking myself with various approaches:
1 and 2 returns
DataTable
while the rest strongly typed result set, so its exactly not apples to apples, but I while time them accordingly.Just the essentials:
The query returned about 1200 rows and 5 fields (run for 100 times). Apart from
Read1
all performed well. Of all I preferRead3
which returns data lazily, as enumerated. This is great for memory if you only need to enumerate it. To have a copy of the collection in memory, you're better off withRead4
orRead5
as you please.