tôi sẽ đề nghị một cái gì đó tương tự như giải pháp của Jason, nhưng sử dụng một wrapper mà thực hiện IDataReader thay vào đó, như vậy:
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'
}
Lưu ý rằng điều này đòi hỏi khá nhiều pass-through mã cho tất cả các thuộc tính không bị ảnh hưởng, nhưng lợi ích là nó là một trừu tượng chung chung mà có thể 'peek' tại bất kỳ vị trí nào trong tập hợp kết quả mà không cần chuyển tiếp về hoạt động 'đọc' tiếp theo.
Cách sử dụng:
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...
}
}
Lưu ý rằng mặc dù cuộc gọi mỗi 'Peek()' sẽ thực sự chuyển sang bản ghi tiếp theo nếu các hoạt động trước đó đã không còn là một 'Peek()'. Giữ sự đối xứng này với thao tác 'Đọc()' cung cấp một cách thực hiện đơn giản hơn và một API thanh lịch hơn.
Ví dụ của bạn không hoạt động vì bản thân giao diện 'IDataReader' không chứa phương thức' .Peek' của bạn. Bạn nên nhập rõ ràng biến phạm vi sử dụng là 'PeekDataReader' hoặc sử dụng' var'. – julealgon