如何最好地检测IDataReader是否为空?

10

看起来IDataReader.Read()至少会返回true一次(如果我对此有误,请告诉我)。那么,你如何判断它是否没有记录,而不仅仅是将其包装在try / catch中?


Ben是正确的。如果一个IDataReader从一个空行集中读取,那么第一次调用Read()将返回false(假设你使用的特定实现是正确编写的)。 - Matt Hamilton
这没有任何意义。如果read应该表示是否有更多的行,则它不能代表一个空条件。例如,在第一次读取时返回false并不表示一个空集。它表示在已经读取了第一条记录之后没有更多的行了。 - Triynko
4个回答

23
if(dr.Read())
{
   //do stuff
}
else
{
 //it's empty
}

通常情况下,您会这样做:

while(dr.Read())
{
}

1
这是我尝试过的,但似乎条件至少会一直为真,但如果尝试从读取器中提取值,则会抛出错误。 - JC Grubbs
3
注意,Read() 会使读取器前进到下一行。因此它不仅仅是检查数据读取器是否包含数据。 - Liam

6

如果你想使用接口,则只有在读取到 false 时才能进行测试。如果你正在寻找通用的 IDataReader 实现,可以尝试使用 DbDataReader 并使用 HasRows 属性。


2
DbDataReader是一个抽象类。 - aku
@aku:是的,这就是重点。IDataReader是一个接口,通常由某种类型的数据读取器实现,该读取器派生自DbDataReader,后者又实现了IDataReader。 - Stefan Steiger
实际上,你永远不会在一个 IDataReader 对象 上调用 Read(),因为这样的东西根本不存在。而且在几乎所有的实现中,你会得到一个 DbdataReader 对象。所以,除非你有将类“降级”回 IDataReader 作为它们的返回类型,否则你可以直接调用它。即使它被降级了,检查一下也是值得的:if (reader is DbDataReader) return ((DbDataReader)reader).HasRows - Nyerguds

3

您可以将 System.Data.IDataReader 直接转换为 System.Data.Common.DbDataReader

using (System.Data.IDataReader IReader = ICommand.ExecuteReader())
{
    if (((System.Data.Common.DbDataReader)IReader).HasRows)
    {
        //do stuff
    }
} // End Using IReader 

这虽然很邪恶,但它(通常)会起作用;)

(假设您的IDataReader实例是由自定义的ADO.NET提供程序实现的,并且不是一些自定义的傻瓜类,它只是实现了IDataReader而不是继承自DbDataReader [它实现了IDataReader])。


2

刚刚遇到了这个问题,找到了一个解决方法...

bool isBeforeEoF;

do
{
    isBeforeEoF = reader.Read();

    if (isBeforeEoF)
    {
        yield return new Foo()
        {
            StreamID = (Guid)reader["ID"],
            FileType = (string)reader["Type"],
            Name = (string)reader["Name"],
            RelativePath = (string)reader["RelativePath"]
        };         
    }

} while (isBeforeEoF);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接