从 Windows 窗体上的单个按钮将数据多次插入 SQL 表
Posted
技术标签:
【中文标题】从 Windows 窗体上的单个按钮将数据多次插入 SQL 表【英文标题】:Inserting data multiple times into an SQL table, from a single button on Windows Forms 【发布时间】:2011-07-26 01:52:15 【问题描述】:我正在将Windows Forms 表单中的数据插入到 SQL 数据库中,如下所示:
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 与此命令关联,必须先关闭。”。
我该如何处理?
*更新:* 我已将按钮单击事件代码更改为如下:
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();**
它的缺点是什么?一种是在单击按钮时一次又一次地打开和关闭连接。
【问题讨论】:
在更新的代码中,请完全删除 cmd.ExecuteReader() 行并取消注释 cmd.ExecuteNonQuery() 行。 【参考方案1】:阅读器需要一个开放的连接,因为您一次只检索一个结果。你会想要为插入、删除和更新做一个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();
任何组合都可以。您可以设置一次连接,然后将命令对象包装在 using 块中。我知道有些人不喜欢嵌套 using 块(因为在幕后是 try(try finally) finally))。
【讨论】:
另外,他应该关闭SqlCommand
,将其放入using
。
更新了几个代码示例,其中一个显示了 using 语句。
@Jason Down:非常感谢您的出色回答,此外,读者是否在每次需要从表中检索一行时都尝试打开连接?
@Jason Down:我只是在使用 cmd.ExecuteReader() ,但没有创建任何阅读器,这种方法会自动创建阅读器吗?
@sqlchild - 对于您的第一个问题:ExecuteReader 调用打开连接并保持打开状态。之后的每次读取都不需要重新打开连接。对于您的第二个问题:一旦您调用 ExecuteReader,它就会创建一个读取器对象,即使您不通过将其分配给变量来使用它。我不确定这个对象什么时候会被标记为垃圾回收。如果你不使用它,最好不要创建它。您最好将 ExecuteReader 更改为 ExecuteNonQuery 以获取 Insert 命令。我想不出一个好的论据来反对它。【参考方案2】:
首先,您应该使用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。
【讨论】:
【参考方案3】:你可以试试:
cmd.ExecuteReader(CommandBehavior.CloseConnection);
【讨论】:
【参考方案4】:杰森说了什么。
虽然您在那里,但也许值得将您的代码稍微更改为:
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();
中的连接
【讨论】:
@sqlchild 在这种情况下,我会修改我的代码,使其与 Jason 的代码非常相似,Jason 现在被标记为答案——我对他的支持。很高兴你把它整理好了:) 先生,如果我在这里使用 SELECT 命令,那么我应该使用数据集,因为它是断开连接的环境,还是在用户直接从数据库中单击按钮时向用户显示数据?哪个更快更好?以上是关于从 Windows 窗体上的单个按钮将数据多次插入 SQL 表的主要内容,如果未能解决你的问题,请参考以下文章
使用窗体上的按钮将值插入Microsoft Access数据库
无法从 Windows 窗体将数据插入 SQL Server
在 C# windows 窗体中的树视图中面临问题,详细信息如下:
C# Windows 窗体使用 OracleDataAdapter 从系统数据表向 Oracle 表插入行