Take a look at these two queries:
-- #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
Query #1 returns 20 rows when I run it in Management Studio.
Query #2 returns the same 20 rows, but I also see the following in the Messages tab:
Informational: The full-text search condition contained noise word(s).
So far, so boring - exactly what I'd expect to happen.
Now, take a look at this C# snippet:
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...
}
}
}
}
When I run this code against query #1 everything behaves as expected - the "do something useful" section gets hit for each of the 20 rows.
When I run it against query #2, nothing happens - the "do something useful" section is never reached.
Now here's where things get a bit more interesting...
If I remove the HasRows
check then everything works as expected - the "do something useful" section gets hit for each of the 20 rows, regardless of which query is used.
It seems that the HasRows
property isn't populated correctly if SQL Server generates a message. The results are returned and can be iterated through using the Read()
method but the HasRows
property will be false.
Is this a known bug in .NET and/or SQL Server, or have I missed something obvious?
I'm using VS2008SP1, .NET3.5SP1 and SQL2008.
EDIT: I appreciate that my question is very similar to this one, and it's almost certainly a manifestation of the same issue, but that question has been bogged down for three months with no definitive answer.
It is used to populate an array of objects with the column values of the current row. It is used to get the next result, when reading the results of SQL statements. It is used to read record from the SQL Server database. To create a SqlDataReader instance, we must call the ExecuteReader method of the SqlCommand object.
A DataReader parses a Tabular Data Stream from Microsoft SQL Server, and other methods of retrieving data from other sources. A DataReader is usually accompanied by a Command object that contains the query, optionally any parameters, and the connection object to run the query on.
I'm the original poster of the refernced question (lost login) and never managed to figure it out. In the end I put it down to bad voodoo, sacrificed neatness and went with something like
bool readerHasRows=false;
while(reader.reader())
{
readerHasRows=true;
doStuffOverAndOver();
}
if (!readerHasRows)
{
probablyBetterShowAnErrorMessageThen();
}
What was really weird was that it worked in one aspx page and not in a another despite the code blocks being almost identical bar the stored procedure used.
Needless to say I'm avoiding .HasRows from now on ;)
EDIT - Management Studio shows messages in the messages tab on the problem procedure in my project too. So that seems to be the cause of the problem. But why would it bugger up .HasRows??
EDIT2 - Confirmed, altered the query to avoid the warning messages and .hasrows is now true.
That certainly is strange behavior - but I am wondering why you need to check HasRows
if you are going to simply iterate the result-set.
The HasRows
property encapsulates a _hasRows
field which gets set in to true
or false
inside SqlDataReader
in many different places for many different reasons. Most of these places it is set to true
if the private TdsParserStateObject
's PeekByte
method returns a number that indicates data is present.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With