在针对SQL Server 2008运行时,SqlDataReader.HasRows中是否存在错误?

时间:2009-01-27 15:14:16

标签: .net sql sql-server sql-server-2008 ado.net

看看这两个问题:

-- #1
SELECT * FROM my_table
WHERE CONTAINS(my_column, 'monkey')

-- #2
SELECT * FROM my_table
WHERE CONTAINS(my_column, 'a OR monkey')  -- "a" is a noise word

在Management Studio中运行时,查询#1返回20行 查询#2返回相同的20行,但我也在消息选项卡中看到以下内容:

  

信息:全文搜索条件包含干扰词。

到目前为止,如此无聊 - 正是我期望发生的事情。

现在,看看这个C#片段:

using (SqlConnection conn = new SqlConnection(...))
{
    SqlCommand cmd = conn.CreateCommand();
    // setup the command object...

    conn.Open();
    using (SqlDataReader dr = cmd.ExecuteReader())
    {
        if (dr.HasRows)
        {
            // get column ordinals etc...

            while (dr.Read())
            {
                // do something useful...
            }
        }
    }
}

当我针对查询#1运行此代码时,一切都按预期运行 - 20行中的每一行都会点击“执行一些有用的”部分。

当我针对查询#2运行它时,没有任何反应 - 从未达到“做有用的事情”部分。

现在这里的事情变得更有趣......

如果我删除了HasRows检查,那么一切都按预期工作 - 无论使用哪个查询,都会为20行中的每一行点击“做一些有用的”部分。

如果SQL Server生成消息,似乎没有正确填充HasRows属性。返回结果并可以使用Read()方法进行迭代,但HasRows属性将为false。

这是.NET和/或SQL Server中的已知错误,还是我错过了一些明显的东西? 我正在使用VS2008SP1,.NET3.5SP1和SQL2008。

编辑:我很欣赏我的问题与this one非常相似,而且几乎可以肯定是同一问题的表现,但这个问题已经陷入困境三个月了明确的答案。

6 个答案:

答案 0 :(得分:6)

我是推荐问题的原始海报(丢失登录信息),但从未设法弄明白。最后,我把它归结为糟糕的伏都教,牺牲了整洁,并采取类似

的方式
bool readerHasRows=false;
while(reader.reader())
{
   readerHasRows=true;
   doStuffOverAndOver();
}
if (!readerHasRows)
{
   probablyBetterShowAnErrorMessageThen();
}

真正奇怪的是它在一个aspx页面中工作而在另一个aspx页面中没有,尽管代码块与所使用的存储过程几乎相同。

毋庸置疑我从现在开始避免.HasRows;)

编辑 - Management Studio也会在项目中的问题流程的消息标签中显示消息。所以这似乎是问题的原因。但是为什么它会起作用.HasRows ??

EDIT2 - 已确认,已更改查询以避免出现警告消息,并且.hasrows现在为真。

答案 1 :(得分:2)

这当然是奇怪的行为 - 但我想知道为什么你需要检查HasRows是否要简单地迭代结果集。

HasRows属性封装了_hasRows字段,由于各种原因,该字段在许多不同的地方设置为truefalseSqlDataReader。如果私有true的{​​{1}}方法返回表示数据存在的数字,则大多数这些地方都设置为TdsParserStateObject

答案 2 :(得分:1)

听起来像HasRows是其中一个值不能保证准确的属性......

我同意前两篇文章(关于直接进入while(dr.Read())并在第一次迭代中获得序数)。另外,为什么不获取数据集而不是数据读取器?如果在这种情况下,您只处理20行,那么与使用数据读取器相比,一次获取整个数据集可能不会产生太大的性能损失。我知道这并没有真正回答你的问题,只是想一个解决方法。

答案 3 :(得分:0)

与Andrew一样,我不确定为什么你不会只使用while循环,以避免额外的GetOrdinal调用的性能损失。您可以使用标志值在第一行执行GetOrdinal调用,然后可以跳过代码。

过去我注意到HasRows存在类似的问题,并且采用了与上面列出的类似的模式,但问题很少。

答案 4 :(得分:0)

尝试以下操作并报告是否成功:

using (SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.SingleResult))

答案 5 :(得分:0)

如果怀疑多个结果集导致此问题,我建议调用NextResult方法。由于第一个结果集似乎是空的,因此使用CommandBehavior.SingleResult不会更改行为,因为仍会返回第一个(空)结果。你可以试试。无论如何,我听说这是一个错误,但我不记得我在哪里阅读它,快速谷歌搜索没有产生任何结果。