none
Execute reader solo me trae un registro RRS feed

  • Pregunta

  • Hola:

    Actualmente estoy desarrollando una aplicación con asp.net 4,c# y SQL server, la arquitectura de mi aplicación es por capas, en una de las capas que es la de repositorio de datos tengo el siguiente procedimiento:

     public static List<DestinoEntidad> ObtenerPorDepartamento(string departamento)
            {
                List<DestinoEntidad> list = new List<DestinoEntidad>();

                using (SqlConnection conn = new SqlConnection(con.ConnectionString.ToString()))
                {
                    conn.Open();

                    string sql = @"SELECT Id, Nombre, (SELECT Nombre FROM Departamentos WHERE Id = Id_departamento ) AS Id_departamento
                                    FROM Destinos
                                    WHERE Id_departamento = '" + departamento + "'";

                    SqlCommand cmd = new SqlCommand(sql, conn);

                    SqlDataReader reader = cmd.ExecuteReader();

                    if (reader.Read())
                    {
                        list.Add(Cargar(reader));
                    }
                }

                return list;

            }

    La consulta que esta en "string sql" debe traer mas de un registro, esta consulta ya la he probado directamente en el management studio de sql server y me trae mas de un registro. Pero cuando esta misma consulta se ejecuta dentro de este procedimiento solo me trae el primer registro.

    ¿Quisiera saber si el problema esta en el executereader del sqlcommand o donde puede estar el error?

    Agradezco su colaboración

    Cordial saludo.

     
    martes, 24 de abril de 2012 15:44

Respuestas

  •  ¡ALARMA DE SQL INJECTION!

    Miguel, para comenzar tu código es susceptible a ataques de inección de SQL.

    Esto no debe hacerse:

    string sql = @"SELECT Id, Nombre, (SELECT Nombre FROM Departamentos WHERE Id = Id_departamento ) AS Id_departamento
                                    FROM Destinos 
                                    WHERE Id_departamento = '" + departamento + "'";

    En su lugar, hazlo así:


    string sql = @"SELECT Id, Nombre, (SELECT Nombre FROM Departamentos WHERE Id = Id_departamento ) AS Id_departamento FROM Destinos WHERE Id_departamento = ?"

    Luego, tienes que añadir un parámetro al SqlCommand. Aquí te dejo unos ejemplos:

    http://dotnetfacts.blogspot.com.es/2009/01/adonet-command-parameters.html

    http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.parameters.aspx

    Dicho esto, pasemos a la cuestión. Permíteme hacerte varias recomendaciones:

    1) En vez de subqueries (un select dentro de un select) puedes hacer un join así:

    SELECT DS.Id, DS.Nombre, DP.Nombre as Id_Departamento
    FROM Destinos DS JOIN Departamentos DP
    ON DS.Id_departamento = DP.Id
    WHERE Id_departamento = ?
    

    2) Si sabes a priori que la consulta va a devolver más de un registro, no uses "if", usa un "while"

    while (reader.Read())
    {
    	list.Add(Cargar(reader));
    }

    Estoy asumiendo que la función Cargar te devuelve un string o un objeto que implementa ToString() para que lo puedas usar como elemento de una lista; o bien que "list" es un objeto de List<T> y Cargar(...) te devuelve un tipo T. Son muchas asunciones, pero espero que te sirva.


    logo osoft
    Si he contestado tu pregunta, por favor marca mi post como respuesta.
    ...Y si mi post te ha servido, márcalo como útil smile

    martes, 24 de abril de 2012 16:11
  • coincido con Yvan usa parametros

    pero por ser sql server la query seria

    string sql = @"SELECT Id, Nombre, (SELECT Nombre FROM Departamentos WHERE Id = Id_departamento ) AS Id_departamento
                                    FROM Destinos 
                                    WHERE Id_departamento = @departamento";

    es con el @ que lo defines

    y los asignas con

    cmd.Parameters.AddWithValue("@departamento", departamento);

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina

    martes, 24 de abril de 2012 16:23

Todas las respuestas

  • hola

    no uses el if

    usa el while

    while(reader.Read())
    {
         list.Add(Cargar(reader));
    }


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina

    • Propuesto como respuesta Hugo Lesiuk martes, 24 de abril de 2012 16:07
    martes, 24 de abril de 2012 15:52
  •  ¡ALARMA DE SQL INJECTION!

    Miguel, para comenzar tu código es susceptible a ataques de inección de SQL.

    Esto no debe hacerse:

    string sql = @"SELECT Id, Nombre, (SELECT Nombre FROM Departamentos WHERE Id = Id_departamento ) AS Id_departamento
                                    FROM Destinos 
                                    WHERE Id_departamento = '" + departamento + "'";

    En su lugar, hazlo así:


    string sql = @"SELECT Id, Nombre, (SELECT Nombre FROM Departamentos WHERE Id = Id_departamento ) AS Id_departamento FROM Destinos WHERE Id_departamento = ?"

    Luego, tienes que añadir un parámetro al SqlCommand. Aquí te dejo unos ejemplos:

    http://dotnetfacts.blogspot.com.es/2009/01/adonet-command-parameters.html

    http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.parameters.aspx

    Dicho esto, pasemos a la cuestión. Permíteme hacerte varias recomendaciones:

    1) En vez de subqueries (un select dentro de un select) puedes hacer un join así:

    SELECT DS.Id, DS.Nombre, DP.Nombre as Id_Departamento
    FROM Destinos DS JOIN Departamentos DP
    ON DS.Id_departamento = DP.Id
    WHERE Id_departamento = ?
    

    2) Si sabes a priori que la consulta va a devolver más de un registro, no uses "if", usa un "while"

    while (reader.Read())
    {
    	list.Add(Cargar(reader));
    }

    Estoy asumiendo que la función Cargar te devuelve un string o un objeto que implementa ToString() para que lo puedas usar como elemento de una lista; o bien que "list" es un objeto de List<T> y Cargar(...) te devuelve un tipo T. Son muchas asunciones, pero espero que te sirva.


    logo osoft
    Si he contestado tu pregunta, por favor marca mi post como respuesta.
    ...Y si mi post te ha servido, márcalo como útil smile

    martes, 24 de abril de 2012 16:11
  • coincido con Yvan usa parametros

    pero por ser sql server la query seria

    string sql = @"SELECT Id, Nombre, (SELECT Nombre FROM Departamentos WHERE Id = Id_departamento ) AS Id_departamento
                                    FROM Destinos 
                                    WHERE Id_departamento = @departamento";

    es con el @ que lo defines

    y los asignas con

    cmd.Parameters.AddWithValue("@departamento", departamento);

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina

    martes, 24 de abril de 2012 16:23
  • Hola Leandro

    Muchas gracias por tu ayuda, que pena contigo la verdad no me había dado cuenta de ese "If".

    Cordial saludo.

    miércoles, 25 de abril de 2012 3:40
  • Hola Leandro:

    No habia tenido en cuenta el SQL INJECTION, voy a tener en cuenta tu sugerencia para corregir el codigo.

    Agradezco tu ayuda 

    cordial saludo

    miércoles, 25 de abril de 2012 3:42
  • Hola Yván Ecarri:

    El escenario de SQL Injection no lo había tenido en cuenta hasta el momento, muchas gracias por tus recomendaciones.

    Agradezco tu ayuda.

    Cordial saludo.

    miércoles, 25 de abril de 2012 3:45