ado.net中的DataReader似乎没有Peek方法.我希望能够在循环阅读器之前执行一些一次性处理,能够查看第一行中的数据而不会导致后续迭代跳过它会很好.完成此任务的最佳方法是什么?
我使用的是sqlDataReader,但最好是实现尽可能通用(即应用于IDataReader或DbDataReader).
解决方法
我建议类似于Jason的解决方案,但使用实现IDataReader的包装器,所以:
sealed public class PeekDataReader : IDataReader { private IDataReader wrappedReader; private bool wasPeeked; private bool lastResult; public PeekDataReader(IDataReader wrappedReader) { this.wrappedReader = wrappedReader; } public bool Peek() { // If the prevIoUs operation was a peek,do not move... if (this.wasPeeked) return this.lastResult; // This is the first peek for the current position,so read and tag bool result = Read(); this.wasPeeked = true; return result; } public bool Read() { // If last operation was a peek,do not actually read if (this.wasPeeked) { this.wasPeeked = false; return this.lastResult; } // Remember the result for any subsequent peeks this.lastResult = this.wrappedReader.Read(); return this.lastResult; } public bool NextResult() { this.wasPeeked = false; return this.wrappedReader.NextResult(); } // Add pass-through operations for all other IDataReader methods // that simply call on 'this.wrappedReader' }
请注意,对于所有未受影响的属性,这确实需要相当多的传递代码,但好处是它是一个通用的抽象,可以“窥视”结果集中的任何位置,而无需继续前进的“读取”操作.
使用:
using (IDataReader reader = new PeekDataReader(/* actual reader */)) { if (reader.Peek()) { // perform some operations on the first row if it exists... } while (reader.Read()) { // re-use the first row,and then read the remainder... } }
请注意,如果前一个操作不是’Peek()’,则每个’Peek()’调用实际上将移动到下一个记录.使用’Read()’操作保持这种对称性提供了更简单的实现和更优雅的API.