2011-03-30 34 views
6

我插入從Windows Forms表單數據到下面的SQL數據庫:插入數據多次到SQL表,從Windows上的一個按鈕窗體

public partial class Form1 : Form 
{ 
    SqlConnection c = new SqlConnection(); 
    string q = "Trusted_Connection = true; "; 

    public Form1() 
    { 
     InitializeComponent(); c.ConnectionString = q; 
     MessageBox.Show("Connecting Database"); 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     string w = "insert into checkmultiuser(username) values (@username)"; 

     SqlCommand cmd = new SqlCommand(w, c); 
     cmd.Parameters.Add("@username", SqlDbType.VarChar); 
     cmd.Parameters["@username"].Value = textBox1.Text; 
     cmd.ExecuteReader(); 
    } 

但是,當我再次點擊該按鈕,那麼它會說「已經有一個與此命令關聯的打開的DataReader,它必須先關閉」。

我該如何處理?

* UPDATE:*我已經改變,因爲下面的按鈕,點擊事件代碼:

private void button1_Click(object sender, EventArgs e) 
{ 
    **c.Open();** 

    string w = "insert into checkmultiuser(username) values (@username)"; 

    SqlCommand cmd = new SqlCommand(w, c); 

    cmd.Parameters.Add("@username", SqlDbType.VarChar); 
    cmd.Parameters["@username"].Value = textBox1.Text; 
    //cmd.ExecuteNonQuery(); 
    cmd.ExecuteReader(); 
    **c.Close();** 
} 

它有哪些缺點?一個會是一次又一次的連接打開和關閉時點擊按鈕。

+0

您的連接在更新後的代碼,請完全刪除該cmd.ExecuteReader()行,並取消對cmd.ExecuteNonQuery()線。 – 2011-03-31 14:22:29

回答

11

閱讀器需要打開連接,因爲您一次只檢索一個結果。您需要爲ExecuteNonQuery()進行插入,刪除和更新。之後您還需要關閉連接。如果您打算執行多個插入操作,則替代方法是將插入操作包裝到循環中。

有幾種方法可以做到這一點。

public partial class Form1 : Form 
{ 
    SqlConnection _cn; 
    SqlCommand _cmd; 

    const string ConnString = "Enter your connection string here"; 
    readonly string _insertQuery; 
    const string UsernameParm = "@username"; 

    public Form1() 
    { 
     InitializeComponent(); 
     _cn = new SqlConnection(ConnString); 

     _cmd = new SqlCommand(InsertQuery, _cn);   
     _cmd.Parameters.Add(UsernameParm, SqlDbType.VarChar); 

     _insertQuery = String.Format("INSERT INTO checkmultiuser(username) VALUES ({0})", 
            UsernameParm); 
    } 

    private void button1_Click(object sender, EventArgs e) 
    {   
     _cmd.Parameters[UsernameParm].Value = textBox1.Text; 

     try 
     { 
      _cn.Open(); 
      _cmd.ExecuteNonQuery(); 
     } 
     catch (Exception ex) // probably best to catch specific exceptions 
     { 
      // handle it 
     } 
     finally 
     { 
      _cn.Close(); 
     } 
    } 
} 

只要確保處置連接和命令對象(當窗體關閉或者其它任何使:如果您打算重複使用相同的連接對象和命令對象一遍又一遍的這種方式是很有用最適合您的應用程序)。

使用塊是一個更安全的替代,但它們將每次處理的對象的(儘管連接默認使用連接池):

public partial class Form1 : Form 
{ 
    const string ConnString = "Enter your connection string here"; 
    readonly string _insertQuery; 
    const string UsernameParm = "@username"; 

    public Form1() 
    { 
     InitializeComponent();    

     _insertQuery = String.Format("INSERT INTO checkmultiuser(username) VALUES ({0})", 
            UsernameParm); 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     using (var cn = new SqlConnection(ConnString)) 
     { 
      using (var cmd = new SqlCommand(InsertQuery, cn)) 
      { 
       cmd.Parameters.Add(UsernameParm, SqlDbType.VarChar); 
       cmd.Parameters[UsernameParm].Value = textBox1.Text; 

       cn.Open(); 
       cmd.ExecuteNonQuery(); 
      } 
     } 
    } 
} 

任何組合也能發揮作用。您可以設置連接一次,只是將命令對象封裝在使用塊中。我知道有些人不是使用嵌套嵌套的粉絲(因爲在後臺嘗試(最終嘗試)))。

+3

另外,他應該把'SqlCommand'放到'using'中。 – 2011-03-30 13:01:04

+0

更新了幾個代碼示例,其中一個示例顯示using語句。 – 2011-03-30 21:14:25

+0

@Jason Down:非常感謝您的偉大答案,讀者在每次需要從表中檢索行時都會嘗試打開連接? – sqlchild 2011-03-31 05:09:03

1

首先,您應該使用ExecuteNonQuery來處理INSERTS,UPDATES和DELETE。當您不期望從數據庫返回值時,使用ExecuteNonQuery。

但是,如果您確實想在另一種情況下使用DataReader,則應該使用它,如下所示。

using (SqlDataReader reader= cmd.ExecuteReader()) 
{ 
     while (reader.Read()) 
     { 
      //Do the reading 
     } 
} 

這確保SqlDataReader一旦完成預定工作就關閉。

另一個潛在的問題可以在連接字符串中修復set MARS (Multiple Active Result Sets) to true

0

你可以試試:

cmd.ExecuteReader(CommandBehavior.CloseConnection); 
2

傑森說什麼。

雖然你在那裏它可能是值得也許改變你的代碼稍微:

private void button1_Click(object sender, EventArgs e) 

{ 
    string w = "insert into checkmultiuser(username) values (@username)"; 
    c.Open(); 
    using (SqlCommand cmd = new SqlCommand(w, c)) 
    { 
    cmd.Parameters.Add("@username", SqlDbType.VarChar); 
    cmd.Parameters["@username"].Value = textBox1.Text; 
    cmd.ExecuteNonQuery(); 
    } 

} 

,以確保正確配置的對象。

也許可以把它放在一個try{}塊太大,並關閉在finally{ c.Close();}

+0

先生,請檢查我的文章的更新部分 – sqlchild 2011-03-31 13:55:36

+0

@sqlchild在這種情況下,我會修改我的代碼,使其與現在標記爲答案的Jason非常相似 - 從我那裏得到的讚揚。很高興你得到它排序:) – SeeSharp 2011-03-31 15:31:19

+0

先生,如果我在這裏使用SELECT命令,那麼我應該使用數據集,因爲它是斷開連接的環境,或顯示數據給用戶,當他直接從數據庫中點擊按鈕?哪個會更快更好? – sqlchild 2011-04-04 05:46:05