while read net from example data .net sql sql-server sql-server-2008 ado.net

.net - net - ¿Hay algún error en SqlDataReader.HasRows cuando se ejecuta en SQL Server 2008?



using sqldatareader vb net (6)

Eche un vistazo a estas dos consultas:

-- #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

La consulta # 1 devuelve 20 filas cuando la ejecuto en Management Studio.
La consulta n.º 2 devuelve las mismas 20 filas, pero también veo lo siguiente en la pestaña Mensajes:

Informativo: la condición de búsqueda de texto completo contiene palabra (s) de ruido.

Hasta ahora, tan aburrido, exactamente lo que esperaba que sucediera.

Ahora, eche un vistazo a este fragmento de 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... } } } }

Cuando ejecuto este código contra la consulta n. ° 1, todo se comporta como se esperaba: se golpea la sección "hacer algo útil" para cada una de las 20 filas.

Cuando lo ejecuto contra la consulta n. ° 2, no ocurre nada; nunca se llega a la sección "hacer algo útil".

Ahora aquí es donde las cosas se ponen un poco más interesantes ...

Si HasRows comprobación de HasRows , todo funciona como se espera: la sección "hacer algo útil" se aplica a cada una de las 20 filas, independientemente de la consulta que se utilice.

Parece que la propiedad HasRows no se llena correctamente si SQL Server genera un mensaje. Los resultados se devuelven y pueden repetirse utilizando el método Read() , pero la propiedad HasRows será falsa.

¿Es este un error conocido en .NET y / o SQL Server, o me he perdido algo obvio?
Estoy usando VS2008SP1, .NET3.5SP1 y SQL2008.

EDITAR: Aprecio que mi pregunta sea muy similar a esta , y es casi seguro una manifestación del mismo problema, pero esa pregunta se ha atascado durante tres meses sin una respuesta definitiva.


Pruebe lo siguiente e informe si fue exitoso:

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


Al igual que con Andrew, no estoy seguro de por qué no usaría el ciclo while para evitar el golpe de rendimiento de las llamadas GetOrdinal adicionales. podría usar un valor de indicador para hacer las llamadas GetOrdinal en la primera fila, y luego se puede omitir el código.

He notado problemas similares con HasRows en el pasado, y he llegado a un patrón similar al mío mencionado anteriormente con problemas mínimos.


Eso ciertamente es un comportamiento extraño, pero me pregunto por qué necesita comprobar HasRows si va a simplemente iterar el conjunto de resultados.

La propiedad HasRows encapsula un campo _hasRows que se establece en true o false dentro de SqlDataReader en muchos lugares diferentes por muchos motivos diferentes. La mayoría de estos lugares se establece en true si el TdsParserStateObject privado TdsParserStateObject de PeekByte devuelve un número que indica que hay datos presentes.


Parece que HasRows es una de esas propiedades cuyo valor no garantiza ser exacto ...

Estoy de acuerdo con las dos publicaciones anteriores (sobre ir directamente a while (dr.Read ()) y obtener los ordinales en la primera iteración. Además, ¿por qué no obtener un conjunto de datos en lugar de un lector de datos? Si en este caso solo está tratando con 20 filas, obtener todo el conjunto de datos de una vez podría no tener mucho éxito en comparación con el uso de un lector de datos. Sé que esto realmente no responde a tu pregunta, sino solo una idea para una solución.


Soy el póster original de la pregunta referida (pérdida de inicio de sesión) y nunca pude resolverlo. Al final lo atribuí al mal vudú, sacrifiqué la pulcritud y fui con algo así como

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

Lo realmente extraño fue que funcionó en una página aspx y no en otra a pesar de que los bloques de código eran casi idénticos, salvo el procedimiento almacenado utilizado.

No hace falta decir que estoy evitando .HasRows a partir de ahora;)

EDITAR - Management Studio muestra mensajes en la pestaña de mensajes en el procedimiento del problema en mi proyecto también. Entonces esa parece ser la causa del problema. Pero, ¿por qué molestaría?. ¿Has pasado?

EDIT2 - Confirmado, alteró la consulta para evitar los mensajes de advertencia y .hasrows ahora es verdadero.


Sugeriría llamar al método NextResult si se sospecha que varios conjuntos de resultados están causando este problema. Dado que el primer conjunto de resultados es el que parece estar vacío, el uso de CommandBehavior.SingleResult no modificará el comportamiento, ya que el primer resultado (vacío) aún se devolverá. Podrías probar eso. De todos modos, he escuchado que esto era un error, pero no recuerdo dónde lo leí, y una búsqueda rápida en Google no produjo ningún resultado.