如何实现在一个DataReader偷看()函数?在一、如何实现、函数、DataReader

2023-09-03 07:47:24 作者:blank [空白]

似乎没有要在ado.net DataReader的一个皮克方法。我希望能够通过我的读者之前,我循环执行一些一次性处理,这将是很好能够看第一行中的数据,而不会使其在后续的迭代被跳过。什么是实现这一目标的最佳方式是什么?

There doesn't seem to be a Peek method on the DataReader in ado.net. I would like to be able to perform some one-off processing before I loop through my reader, and it would be nice to be able to look at the data in the first row without causing it to be skipped by the subsequent iteration. What is the best way to accomplish this?

我使用的是 SqlDataReader的,但preferably的实施将尽可能地通用(即适用于的IDataReader DbDataReader )。

I am using a SqlDataReader, but preferably the implementation would be as general as possible (i.e. apply to IDataReader or DbDataReader).

推荐答案

我会建议类似杰森的解决方案的东西,但使用实现IDataReader的,而不是一个包装,因此:

I would suggest something similar to Jason's solution, but using a wrapper that implements IDataReader instead, so:

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'
}

请注意,这确实需要相当多的直通code所有未受影响的特性,但它的好处是,它是一个可以偷看在结果的任何位置设置而不向前移动一个通用的抽象在随后的读操作

Note that this does require quite a bit of pass-through code for all the unaffected properties, but the benefit is that it is a generic abstraction that can 'peek' at any position in the result set without moving forward on the subsequent 'read' operation.

要使用:

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...
    }
}

请注意,虽然每一个'皮克()调用实际上会移动到下一个记录,如果previous操作是不是也有'皮克()。保持这种对称性的阅读()操作提供了一个简单的实现和更优雅的API。

Note though that every 'Peek()' call will actually move to the next record if the previous operation was not also a 'Peek()'. Keeping this symmetry with the 'Read()' operation provides a simpler implementation and a more elegant API.