¿Intento no válido de llamar a Leer cuando el lector está cerrado?

Estoy ejecutando un DbDataReader en una consulta para eliminar elementos de una lista desplegable si ya están adjuntos a un envío específico, y sigo recibiendo un error que me dice que el lector está cerrado. No veo por qué mi lector aparece como cerrado aquí. ¿Qué me estoy perdiendo?

 protected void Page_Load(object sender, EventArgs e)
{

    string x = Request.QueryString["SubId"];
    string connectionString = System.Configuration.ConfigurationManager.
        ConnectionStrings["MyConnectionString"].ConnectionString;
    string displayQuery = "SELECT CustName, CustAdd, CustCity, CustState, " +
        "CustZip FROM Customer WHERE SubId =" + x;
    string broQuery = "SELECT EntityType FROM Broker WHERE SubId =" + x;
    string ddlQuery = "SELECT ProductId FROM SubmissionProducts " +
        "WHERE SubmissionId =" + x;
    using (SqlConnection displayConn = new SqlConnection(connectionString))
    {
        displayConn.Open();
        SqlCommand DlistCmd = new SqlCommand(ddlQuery, displayConn);

        using (SqlDataReader Ddldr = DlistCmd.ExecuteReader())
        {
            while (Ddldr.Read())
            {

                switch (Ddldr.GetInt32(0))
                {
                    case 1:
                        DdlProductList.Items.RemoveAt(1);
                        break;
                    case 2:
                        DdlProductList.Items.RemoveAt(2);
                        break;
                    case 3:
                        DdlProductList.Items.RemoveAt(3);
                        break;
                    case 4:
                        DdlProductList.Items.RemoveAt(4);
                        break;
                    case 5:
                        DdlProductList.Items.RemoveAt(5);
                        break;
                    case 6:
                        DdlProductList.Items.RemoveAt(6);
                        break;
                    case 7:
                        DdlProductList.Items.RemoveAt(7);
                        break;
                    default:
                        break;
                }
                Ddldr.Close();
            }

        }

preguntado el 16 de mayo de 11 a las 17:05

esto es solo una suposición, pero ¿quiere ejecutar un comando DDL aquí? -

@Adrian: Eso es lo que using....es para... -

@Gabriel Creo que está usando DDL aquí para referirse a "DropdownList", un control ASP.NET en su página. -

¿Quizás puedas publicar una mayor parte de tu código? -

Entonces, si proporcionó todo el código desde el principio, obtendría la respuesta correcta en solo minutos. -

2 Respuestas

No llames Ddldr.Close();, especialmente dentro del while. De esta manera, está haciendo una primera iteración, cerrando el lector y, por supuesto, la segunda iteración explotará cuando se cierre el lector. El using declaración se encargará de ello. Simplemente elimine esta línea de su código.

De modo que:

using (SqlDataReader Ddldr = DlistCmd.ExecuteReader())
{
    while (Ddldr.Read())
    {
        switch (Ddldr.GetInt32(0))
        {
            ... your cases here
            default:
                break;
        }
    }
}

También las siguientes líneas:

string x = Request.QueryString["SubId"];
string displayQuery = "SELECT CustName, CustAdd, CustCity, CustState, CustZip FROM Customer WHERE SubId =" + x;
string broQuery = "SELECT EntityType FROM Broker WHERE SubId =" + x;
string ddlQuery = "SELECT ProductId FROM SubmissionProducts WHERE SubmissionId =" + x;

apesta como un montón de mierda. Debería utilizar consultas parametrizadas y absolutamente nunca escribir un código como este o su aplicación será vulnerable a la inyección de SQL. Cada vez que utilice una concatenación de cadenas al escribir una consulta SQL, debería sonar una alarma que le indicará que lo está haciendo mal.

Entonces aquí viene la forma correcta de hacer esto:

protected void Page_Load(object sender, EventArgs e)
{
    string x = Request.QueryString["SubId"];
    string connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString;
    using (var conn = new SqlConnection(connectionString))
    using (var cmd = conn.CreateCommand())
    {
        conn.Open();
        cmd.CommandText = "SELECT ProductId FROM SubmissionProducts WHERE SubmissionId = @SubmissionId";
        cmd.Parameters.AddWithValue("@SubmissionId", x)

        using (var reader = cmd.ExecuteReader())
        {
            while (Ddldr.Read())
            {
                switch (reader.GetInt32(reader.GetOrdinal("ProductId")))
                {
                    ... your cases here
                    default:
                        break;
                }
            }

        }
    }
}

contestado el 16 de mayo de 11 a las 22:05

Gracias, Darin. Necesitaba comprender la forma en que se realizaron las iteraciones para reconocer que la declaración dr.close tenía que desaparecer. Es mi primera ronda con la codificación, y mi entrenador me prohibió específicamente parametrizar en aras de la simplicidad (el sitio no es para una implementación real), pero sí, estoy de acuerdo, las consultas no parametrizadas están pidiendo inyección. - Solucionador de problemas de Ace

Elimine esta línea:

Ddldr.Close();

Respondido 12 ago 13, 14:08

Jaja, me encanta cuando dos horas de mi vida se reducen a 14 caracteres de código erróneo. Gracias Hogan. - Solucionador de problemas de Ace

@Brazos - Sí, es un fastidio. Pero cada vez que me pasa me animo con el pensamiento "No volveré a hacer eso". - Hogan

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.