Yo suelo escribir mi DataReader código como este:

try
{
    dr = cmd.ExecuteReader(CommandBehavior.SingleResult);
    while (dr.Read())
    {
        //Do stuff
    }
}
finally
{
    if (dr != null) { dr.Close(); }
}

Es seguro para reemplazar el try y finally con sólo un using bloque alrededor de la DataReader‘s de la creación? La razón por la que me pregunto es porque en todos los ejemplos de Microsoft he visto que el uso de un uso para la conexión, pero siempre de forma explícita llamada Close() en el DataReader.

Heres un ejemplo de
La recuperación de Datos Utilizando un DataReader (ADO.NET):

static void HasRows(SqlConnection connection)
{
    using (connection)
    {
        SqlCommand command = new SqlCommand(
          "SELECT CategoryID, CategoryName FROM Categories;",
          connection);
        connection.Open();

        SqlDataReader reader = command.ExecuteReader();

        if (reader.HasRows)
        {
            while (reader.Read())
            {
                Console.WriteLine("{0}\t{1}", reader.GetInt32(0),
                    reader.GetString(1));
            }
        }
        else
        {
            Console.WriteLine("No rows found.");
        }
        reader.Close();
    }
}
  • Como una nota del lado, la mayoría de los MS ejemplos que he visto son demasiado complicadas o no realmente aprovechar mucho de las características del lenguaje disponible. En parte es porque simplemente rodar sobre el código de ejemplo de las versiones anteriores y realmente sólo comprobar que todavía funciona. Mi conjetura es que este código no es mantenido por sus más brillantes debido a que el código nunca es inteligente o eficiente.
  • de la calidad del código de ejemplo, he sospechado durante años que es escrito y mantenido por nivel de entrada a los internos, no de las personas que en realidad diseñado las clases en el primer lugar. Se trata de cosas como Microsoft mediocre .NETO de la documentación que tipo de me hacen mirar hacia adelante a SO la nueva documentación de expansión.
  • Posibles duplicados de Es necesario cerrar manualmente y disponer de SqlDataReader?
  • no duplicados, en mi opinión. Este de aquí se pregunta si un using bloque cerca de un lector de datos, el otro le pregunta si es necesario cerrarlo. No es lo mismo.
  • ese es un buen punto.
InformationsquelleAutor user169867 | 2010-01-28

4 Comentarios

  1. 18

    Sí. using llamadas Disponer. Llamar a Dispose en SqlDataReader cierra.

    Este es el pseudo-código de SqlDataReader obtenida de Reflector:

        public void Dispose()
        {
            this.Close();
        }
    
        public override void Close()
        {
            if( !IsClosed )
                CloseInternal(true);
        }
    
        private void CloseInternal(bool closeReader)
        {
            try
            {
                //Do some stuff to close the reader itself
            }
            catch(Exception ex)
            {
                this.Connection.Abort();
                throw;
            }
    
            if( this.Connection != null && CommandBehavior.CloseConnection == true )
            {
                this.Connection.Close();
            }
        }
  2. 4

    Normalmente, using() llamadas Dispose() y que llama a close() en turno.

    En caso de un DataReader, el Cierre se llama sólo cuando CommandBehavior.CloseConnection (ver comentarios de este artículo http://weblogs.asp.net/joseguay/archive/2008/07/22/ensure-proper-closure-amp-disposal-of-a-datareader.aspx).

    EDICIÓN: Este artículo dice algo interesante:

    El método Close() en el
    SqlDataReader llama a un InternalClose()
    el método, que no llamar a Dispose.
    Tenga en cuenta que anteriormente hemos dicho que la
    manera correcta de hacerlo era tener
    su cierre llamar a dispose. Para hacerlo
    aún más confuso el Dispose()
    el método realmente llama la Close()
    método por lo que para este objeto de la orden es
    invierte.

  3. 1

    A diferencia del ejemplo aquí, mi práctica ha sido la de emplear un bloque using para la conexión, el comando y el lector. Tenga en cuenta que usted puede apilar anidada utilizando bloques para reducir la sangría costo.

    static void HasRows(SqlConnection connection)
    {
        using (connection)
        using (SqlCommand command = new SqlCommand(
        "SELECT CategoryID, CategoryName FROM Categories;",
        connection))
        {
            connection.Open();
            using (SqlDataReader reader = command.ExecuteReader())
            {
                if (reader.HasRows)
                {
                    while (reader.Read())
                    {
                        Console.WriteLine("{0}\t{1}", reader.GetInt32(0),
                            reader.GetString(1));
                    }
                }
                else
                {
                    Console.WriteLine("No rows found.");
                }
                reader.Close();
            }   
        }
    }
  4. 1

    De lo que puedo recordar, si se produce una excepción en un bloque using, entonces el método Dispose se llama todavía en el objeto. Por lo general, tienen una instrucción de Uso para todos los objetos desechables, sin un Try..Catch.

    EDIT: Olvidaba decir que para algunos objetos, llamar a Dispose a su vez llama a Cerca de ese objeto.

Dejar respuesta

Please enter your comment!
Please enter your name here