C# 检查是否已对SqlDataReader调用read()

C# 检查是否已对SqlDataReader调用read(),c#,.net,sql,C#,.net,Sql,我正在编写一些助手函数,这些函数使用SqlDataReader并处理结果。现在,通常您会这样构造循环: while(reader.read()){ // Read fields } 但是我将把函数传递给一个已经定位在一行上的读取器,在这种情况下,我希望它处理当前行。如果在调用函数之前未调用read(),则上述代码将只输出整个结果集 我希望函数执行如下操作: if(!reader._dataReady) rowExists = reader.read() // Read whi

我正在编写一些助手函数,这些函数使用SqlDataReader并处理结果。现在,通常您会这样构造循环:

while(reader.read()){
    // Read fields
}
但是我将把函数传递给一个已经定位在一行上的读取器,在这种情况下,我希望它处理当前行。如果在调用函数之前未调用read(),则上述代码将只输出整个结果集

我希望函数执行如下操作:

if(!reader._dataReady)
    rowExists = reader.read() // Read 
while(rowExists){
    // read fields
    rowExists = reader.read()
}

_dataReady是SqlDataReader的实际成员,似乎做了我需要的事情,但它是私有的!除了尝试读取字段并捕获异常之外,肯定有一种方法可以确定读取器是否位于实际行上。

您可以使用FieldCount属性。根据,如果未定位在有效记录集中,则返回零

其他一些解决方案:

  • 执行
    Read()
    循环完全在助手方法之外(并且始终仅对当前行进行操作)

  • 执行
    Read()
    完全在helper方法中循环,并始终向其传递尚未升级的新数据读取器

  • 在数据读取器外部执行第一次
    Read()
    ,在helper方法中继续
    Read()
    循环,并始终假定数据读取器已前进到第一条记录

  • 可能是杀伤力过大:编写IDataReader的包装实现,将所有调用转发给底层数据读取器(可能通过构造函数传入),但公开一个指示是否调用过Read的属性


  • 这有点像超载,但以下几点应该可以:

    rowExists = reader.FieldCount > 0;
    

    我怀疑您会发现自己在代码的不同位置执行Read()的设计时遇到问题。尝试在方法中只执行数据操作(并将其作为
    IDataRecord
    而不是
    IDataReader
    传递),并将记录遍历逻辑留给调用者。

    为什么不只将SqlDataReader子类化,并创建Read()方法?现在,我的所有项目中都有:

    public class SafeDataReader : IDataReader, SqlDataReader
    {
        public IDataReader reader {get;set;}
        public int GetInt32(string aFieldName, int aDefault);
        public int? GetInt32Nullable(string aFieldName);
        .... 
    }
    

    反思是危险的,但往往是有用的。这是一个分机

    public static bool? DataReady(this SqlDataReader rd) {
                var sharedState = rd.GetType()?.GetField("_sharedState", 
                     BindingFlags.NonPublic | BindingFlags.Instance)?.GetValue(rd);
                return (bool?)sharedState?.GetType().GetField("_dataReady",
                    BindingFlags.NonPublic | BindingFlags.Instance)?.GetValue(sharedState);
     }
    

    刚测试的。

    中的信息,如果尚未调用read(),则fieldCount属性不会返回零。如果SQL根本没有返回结果集,它只返回零。为了澄清:Trent是正确的-如果读卡器已填充,但未调用
    Read()
    ,并且读卡器有带字段的行,然后,
    FieldCount
    将设置为结果集中的字段数。您不能强制用户在调用帮助程序之前始终进行读取吗?如果不这样做,将导致一个异常,您可以捕获、包装和重新调用该异常。你的目标受众显然是开发人员,所以强迫他们遵循你的API。好主意。我可以存储跟踪读卡器位置的枚举:-SafeDataReaderPosition.BeforeRows-SafeDataReaderPosition.OnRow-SafeDataReaderPosition.EndOfFile。所有这些都不必通过使用数据集来牺牲异步性能。不知道为什么这还不是实现的一部分。。。