2013-10-28 51 views
3

我正在創建密碼更改表單。當我執行表單並填充文本框時,它會給消息There is already and open DataReader associated with this command which must be closed first一個例外。在創建密碼更改表單時遇到異常

他是我使用的代碼:

private bool CompareStrings(string string1, string string2) 
     { 
      return String.Compare(string1, string2, true, System.Globalization.CultureInfo.InvariantCulture) == 0 ? true : false; 
     } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     try 
     { 
      SqlConnection con1 = new SqlConnection(); 
      con1.ConnectionString = "data source=.;Initial catalog=inventory;Integrated Security=true"; 
      con1.Open(); 

      SqlCommand cmd = new SqlCommand("SELECT ISNULL(username, '') AS username, ISNULL(password,'') AS password FROM login WHERE username='" + textBox1.Text + "' and password='" + textBox2.Text + "'", con1); 

      SqlDataReader dr = cmd.ExecuteReader(); 

      string userText = textBox1.Text; 
      string passText = textBox2.Text; 

      while (dr.Read()) 
      { 
       if (this.CompareStrings(dr["username"].ToString(), userText) && 
        this.CompareStrings(dr["password"].ToString(), passText)) 
       { 
        SqlCommand cmd2 = new SqlCommand("UPDATE login SET password='" + textBox3.Text + "'where username='" + textBox1.Text + "'", con1); 
        cmd2.ExecuteNonQuery(); 
        MessageBox.Show("Password Changed Successfully"); 
       } 
       else 
       { 
        MessageBox.Show("Incorrect Old password");       
       } 

      } 

      dr.Close(); 

      con1.Close(); 

     } 
     catch (Exception ex) 
     { 
      MessageBox.Show(ex.Message); 
     } 

回答

2

SqlDataReader是相同的連接上打開時,不能執行的命令。您可以執行以下兩項操作之一來更改代碼:

  1. 創建第二個連接並在該第二個連接上運行更新查詢。

  2. 存儲來自閱讀器的數據,關閉閱讀器並稍後更新所有數據。在你的情況,你可以存儲所有的用戶名更新和使用Username in (<yourlisthere>)

+0

中的散列密碼的結果是否一致,但是當輸入錯誤的密碼時,它不會顯示存儲在'其他'的說法。 –

+1

您選擇了哪種解決方案? – Szymon

+0

第一個.... –

2

在一個更新查詢更新它們當您打開一個DataReader的連接僅用使用DataReader來的請求。用於更新登錄表的SqlCommand無法運行。

除非你添加到您的ConnectionString

MultipleActiveResultSets = True; 

Here you can find the reference to MARS

而且here the words from MSDN有關DataReader

當正在使用SqlDataReader對象時,關聯的SqlConnection是 忙於服務SqlDataReader中,並且沒有其他的操作可以在SqlConnection上執行其他操作 其他操作比關閉它。 的情況就是這種情況,直到SqlDataReader的Close方法被調用。例如, 直到調用關閉之後才能檢索輸出參數。

作爲一個附註,但非常重要。不要使用字符串連接來構建sql命令。總是使用參數化查詢

string cmdText = "UPDATE login SET [email protected] where [email protected]"; 
using(SqlCommand cmd2 = new SqlCommand(cmdText, con1)) 
{ 
    cmd2.Parameters.AddWithValue("@pwd", textBox3.Text); 
    cmd2.Parameters.AddWithValue("@usr", textBox1.Text); 
    cmd2.ExecuteNonQuery();  
} 

參數化查詢將避免Sql Injection的問題,讓您簡化命令文本。
對於代碼開始處的SELECT查詢也是如此。不要相信來自用戶的輸入

您應該知道的另一個問題是在數據庫中存儲明文密碼。從安全的角度來看,這被認爲是一種非常糟糕的做法。你應該使用散列函數給你密碼並存儲結果。在檢查正確的密碼時,您重複用戶輸入上的散列函數,並檢查結果與存儲在數據庫

+0

感謝有關查詢的其他信息。 我不知道這個事實。 感謝您提升我的知識水平並提供您所提供的解決方案。 –

+0

可以請你給我提供一個鏈接,我可以學習使用哈希函數,因爲我不知道它... –

+1

[這是一個老問題](http://stackoverflow.com/questions/13450201/working-with-registry -in-c-sharp-2-0-windows-forms/13450315#13450315)涵蓋了有關哈希和加密的東西 – Steve