C# 检查是否已对SqlDataReader调用read()
我正在编写一些助手函数,这些函数使用SqlDataReader并处理结果。现在,通常您会这样构造循环:C# 检查是否已对SqlDataReader调用read(),c#,.net,sql,C#,.net,Sql,我正在编写一些助手函数,这些函数使用SqlDataReader并处理结果。现在,通常您会这样构造循环: while(reader.read()){ // Read fields } 但是我将把函数传递给一个已经定位在一行上的读取器,在这种情况下,我希望它处理当前行。如果在调用函数之前未调用read(),则上述代码将只输出整个结果集 我希望函数执行如下操作: if(!reader._dataReady) rowExists = reader.read() // Read whi
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()
循环,并始终假定数据读取器已前进到第一条记录这有点像超载,但以下几点应该可以:
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。所有这些都不必通过使用数据集来牺牲异步性能。不知道为什么这还不是实现的一部分。。。