2011-05-16 88 views
1

我在查询上运行DbDataReader以删除下拉列表中的项目(如果它们已附加到特定提交中),并且我不断收到错误,告诉我该阅读器已关闭。看不出为什么我的读者在这里被视为封闭。我错过了什么?无法尝试打电话阅读器关闭时读取?

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(); 
      } 

     } 
+0

这只是一种猜测,但你的意思是在这里执行一个DDL命令? – 2011-05-16 17:48:45

+0

我真的不喜欢这种使用'使用' – 2011-05-16 17:48:46

+8

@阿德里安:这就是'使用'....是为... – 2011-05-16 17:50:50

回答

9

不要叫Ddldr.Close();,尤其是while内。这样,您正在进行第一次迭代,关闭阅读器,第二次迭代当然会在阅读器关闭时进行。 using声明将照顾它。只需从代码中删除此行。

所以:

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

而且下面几行:

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; 

臭像一堆s..t的。你应该使用参数化查询,绝对不要写这样的代码,否则你的应用程序将很容易被SQL注入。每次在编写SQL查询时使用字符串连接时,警报都会响起,告诉您您做错了。

所以在这里谈到这样做的正确方法:

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; 
       } 
      } 

     } 
    } 
} 
+0

谢谢Darin。我需要了解迭代的执行方式,以确认dr.close语句必须执行。这是我第一次与编码有关,我的培训师专门为了简化而禁止参数化(该网站不适用于实际部署),但是,我同意,没有参数的查询正在寻求注入。 – 2011-05-16 18:53:58

2

删除此行:

Ddldr.Close(); 
+0

哈哈,当我生命中的两个小时减少到14个字符的错误代码时,就得爱它。谢谢Hogan。 – 2011-05-16 18:57:33

+1

@Brazos - 是的,这是一种痛苦。但每次它发生在我身上时,我都会为“我不会再这样做”的想法感到高兴。 – Hogan 2011-05-16 18:58:48

相关问题