只是为了好玩,我尝试在下面创建一个类。测试肯定很麻烦。
在解释为什么会很痛苦之前,我会为您提供一个免去麻烦的借口。如果您的班级正在创建IDataReaders,则可能没有充分的理由将它们传递给调用者。您可以从它们中读取数据并将 that 传递给调用者。调用者需要阅读器而不仅仅是实际数据有什么好的理由吗?打开和关闭数据阅读器是您想要完成的事情,而无需过多参与此过程,因此,如果您可以打开它,获取您需要的内容,然后关闭它,那是理想的。
当我们在IDataReader 中从一个结果集前进到下一个结果集时,通常是在进行单个调用的上下文中,因此更容易了解结果集是什么。我们刚刚调用了过程 XYZ,它返回两个结果集,所以我们必须检查这两个结果集。我不想处理具有大量结果集的IDataReader,尤其是当它是一堆人为组合的较小结果集时。您必须跟踪大量结果集并在不同的方法之间切换以读取它们,因为它们包含不同的列。
还有那些开放连接的问题。我们通常在完成阅读器后关闭连接。但现在还不清楚该连接何时关闭。你怎么知道哪个连接属于哪个阅读器?如果您关闭另一个阅读器的连接,而另一个阅读器仍在使用它会怎样?
所以这里有一个大概的样子。我显然没有测试这个。如果调用NextResult 并且当前阅读器中没有下一个结果,您将必须跟踪哪个是当前阅读器并处理前进到下一个阅读器。而且您必须关闭阅读器并确保它们都被处理掉。这可以进行测试,但只是测试会让人头疼,这通常是一个很好的警告,不要做某事。
public class AggregateDataReader : IDataReader
{
private readonly Queue<IDataReader> _readers;
private IDataReader _current;
public AggregateDataReader(IEnumerable<IDataReader> readers)
{
_readers = new Queue<IDataReader>(readers);
}
private bool AdvanceToNextReader()
{
_current?.Dispose();
var moreReaders = _readers.Any();
if (moreReaders) _current = _readers.Dequeue();
return moreReaders;
}
public bool NextResult()
{
if (_current == null) return false;
if (_current.NextResult()) return true;
return AdvanceToNextReader();
}
public bool Read()
{
return _current.Read();
}
public void Dispose()
{
_current?.Dispose();
while (_readers.Any()) _readers.Dequeue().Dispose();
}
public string GetName(int i)
{
return _current.GetName(i);
}
... lots of these...
public byte GetByte(int i)
{
return _current.GetByte(i);
}
public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
{
return _currentGetBytes(i, fieldOffset, buffer, bufferoffset, length);
}
... etc...
public void Close()
{
_current?.Close();
while (_readers.Any()) _readers.Dequeue().Close();
}
... etc...
}