2011-12-14 110 views
2

我的代碼:asp.net的DataReader,必須關閉

SqlConnection con = new SqlConnection(WebConfigurationManager.ConnectionStrings["myConnectionString"].ConnectionString); 
SqlCommand cmd = new SqlCommand(); 
//.......... 
cmd.CommandText = "SELECT * FROM TempQn WHERE creatorId= '" + 
Session["administratorID"].ToString() + "'"; 
dr = cmd.ExecuteReader(); 
while (dr.Read()) 
{ 
    int ids = Int32.Parse(dr["QuestionID"].ToString()); 
    cmd.CommandText = " INSERT INTO Answers (QuestionId,Answer) Select c.QnId, c.Answer From TempAns c Where c.Id = " + ids + " "; 
    cmd.ExecuteNonQuery(); //this line 
} 
dr.Close(); 

的錯誤是:

已經沒有與此命令必須先關閉相關聯的打開的DataReader。

什麼樣的命令應該取代cmd.ExecuteNonQuery();

+1

首先,使用字符串連接構建sql查詢是一種不好的做法,因爲它可能導致安全漏洞。改用SqlParameters。 – 2011-12-14 09:19:00

+1

第二,你不能在單個sql查詢中做你在做什麼嗎? – 2011-12-14 09:19:40

+0

我想你打開另一個datareader代替.......? – 2011-12-14 09:20:11

回答

3

只要DataReader是「活動的」,就不能執行任何進一步的SQL語句。

爲了克服這個問題,SQL語句的商店名單,然後閱讀後exeucute他們:

cmd.CommandText = "SELECT * FROM Question WHERE SurveyID= '" + sID + "'";  
dr = cmd.ExecuteReader(); 
List<string> arrSQL = new List<string>(); 
while (dr.Read()) 
{ 
    int ids = Int32.Parse(dr["QuestionID"].ToString()); 
    arrSQL.Add("INSERT INTO Answers (QuestionId,Answer) Select c.QnId, c.Answer From TempAns c Where c.Id = " + ids + " "); 
} 
dr.Close(); 

arrSQL.ForEach(strSQL => 
{ 
    cmd.CommandText = strSQL; 
    cmd.ExecuteNonQuery(); 
}); 

您當前的代碼很容易受到雖然SQL注入攻擊,是不是好的做法 - 你更好的使用,而不是參數注入價值的原始SQL - 這裏是如何做到這一點:

cmd.CommandText = "SELECT * FROM Question WHERE [email protected]"; 
cmd.Parameters.AddWithValue("@id", sID); 
dr = cmd.ExecuteReader(); 
List<int> arrQuestions = new List<int>(); 
while (dr.Read()) 
{ 
    int ids = Int32.Parse(dr["QuestionID"].ToString()); 
    arrQuestions.Add(ids); 
} 
dr.Close(); 

cmd.CommandText = "INSERT INTO Answers (QuestionId, Answer) Select c.QnId, c.Answer From TempAns c Where c.Id = @id"; 
arrQuestions.ForEach(id => 
{ 
    cmd.Parameters["@id"].Value = id; 
    cmd.ExecuteNonQuery(); 
}); 
0

您需要聲明新的命令對象,因爲cmd已被用於讀取數據,當您嘗試將其用於insert語句時。另外,不要使用sql命令中的字符串連接,這是一種不好的做法,並且容易受到SQL注入的影響。使用參數。

1

您已經有一個與「cmd」關聯的命令。

dr = cmd.ExecuteReader(); 
      while (dr.Read()) 
      { 
       int ids = Int32.Parse(dr["QuestionID"].ToString()); 
       SqlCommand sqlCmd = new SqlCommand("INSERT INTO Answers (QuestionId,Answer) Select c.QnId, c.Answer From TempAns c Where c.Id = " + ids + " "); 
       sqlCmd.ExecuteNonQuery(); //this line 
      } 
      dr.Close(); 

所以就像上面給出的一樣,爲插入創建一個新的命令。

1

這個單一查詢應該做的工作(不知道你確切的數據模型,如果需要適應):

INSERT INTO Answers (QuestionId,Answer) 
Select c.QnId, c.Answer 
From TempAns c 
inner join Question q on c.QnId = q.Id 
where q.SurveyID = @SurveyID 

爲了避免SQL注入,使用C#代碼:

cmd.CommandTest = @"INSERT INTO Answers (QuestionId,Answer) 
    Select c.QnId, c.Answer 
    From TempAns c 
    inner join Question q on c.QnId = q.Id 
    where q.SurveyID = @SurveyID"; 

SqlParameter param = cmd.Parameters.Add("@SurveyID", SqlDbType.Int); 
param.Value = yourSurveyId; 

cmd.Open(); // it would be better to check the status before 
cmd.ExecuteNonQuery(); 
cmd.Close(); 
1

而不是使用第二連接對象,你可以改變你的連接字符串,並使用MARS(Multiple active result set)用於這一目的。將以下語句添加到您的連接字符串:

MultipleActiveResultSets=True 

編輯: 而像其他的說,使用SqlParameters爲您的參數,而不是字符串連接。這不僅是一個安全問題,也是一個巨大的性能影響!

相關問題