同时执行Insert语句与存储过程时文本框参数为空问题排查
问题根源与解决方案
首先,直接说最核心的问题:你在btnsave_Click方法里,先调用了this.Close(),之后才执行recorduserlog()。当窗体关闭后,所有控件(包括txtfullname)都会被销毁/释放,这时候再去读取txtfullname.Text自然是空值。而单独执行存储过程时,窗体还处于活跃状态,控件正常,所以能拿到正确的值。
修复步骤
- 调整执行顺序:把
recorduserlog()移到this.Close()之前,确保读取控件值时窗体还没关闭:
MessageBox.Show("Successfully Created a User Account for '" + txtfullname.Text + "'.", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information); // 先记录日志,再关闭窗体 recorduserlog(); this.Close();
- 解决其他潜在问题:你的代码还有几个需要优化的点,避免后续出现更多问题:
- 避免SQL注入:当前的Insert语句用了字符串拼接,这会带来严重的SQL注入风险,改成参数化查询:
SqlCommand cmd2 = new SqlCommand("insert into endusers(usern,passw,fullname,accesslevel,stats)values(@usern,@passw,@fullname,@accesslevel,@stats)", conn); cmd2.Parameters.AddWithValue("@usern", UserName); cmd2.Parameters.AddWithValue("@passw", Password); cmd2.Parameters.AddWithValue("@fullname", txtfullname.Text); cmd2.Parameters.AddWithValue("@accesslevel", ssfapclass); cmd2.Parameters.AddWithValue("@stats", 1); - 连接对象管理混乱:你同时用了
sqlcon和conn两个连接对象,而且sqlcon.Dispose()的时机不对,建议用using语句自动管理连接的打开和关闭,确保资源正确释放:// 用using包裹连接对象,自动释放资源 using(SqlConnection conn = new SqlConnection(Properties.Settings.Default.myconnectionstring)) { conn.Open(); // 这里写参数化的Insert命令和执行代码 cmd2.ExecuteNonQuery(); } - 存储过程里的日期参数:直接传递
DateTime.Now而不是转成字符串,数据库的日期类型可以直接接收DateTime对象,避免格式问题:cmd.Parameters.Add(new SqlParameter("@datelog", DateTime.Now));
- 避免SQL注入:当前的Insert语句用了字符串拼接,这会带来严重的SQL注入风险,改成参数化查询:
完整修复后的关键代码片段
private void btnsave_Click(object sender, EventArgs e) { if (txtusername.Text != "" && txtaccesscode.Text != "" && txtfullname.Text != "" && cmbaccessleve.Text != "") { if (txtaccesscode.Text.Trim().ToLower() == txtconfirm.Text.Trim().ToLower()) { string UserName = txtusername.Text; string Password = adduser.Encrypt(txtaccesscode.Text); // 使用using管理连接 using(SqlConnection conn = new SqlConnection(Properties.Settings.Default.myconnectionstring)) { conn.Open(); // 参数化Insert语句 SqlCommand cmd2 = new SqlCommand("insert into endusers(usern,passw,fullname,accesslevel,stats)values(@usern,@passw,@fullname,@accesslevel,@stats)", conn); cmd2.Parameters.AddWithValue("@usern", UserName); cmd2.Parameters.AddWithValue("@passw", Password); cmd2.Parameters.AddWithValue("@fullname", txtfullname.Text); cmd2.Parameters.AddWithValue("@accesslevel", ssfapclass); cmd2.Parameters.AddWithValue("@stats", 1); cmd2.ExecuteNonQuery(); } MessageBox.Show("Successfully Created a User Account for '" + txtfullname.Text + "'.", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information); // 先记录日志,再关闭窗体 recorduserlog(); this.Close(); } else { MessageBox.Show("Access Code and Confirmation Code doesn't match!.. Please Check..", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } else { MessageBox.Show("Please fill all the fields!..", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void recorduserlog() { // 同样用using管理连接 using(SqlConnection sqlcon = new SqlConnection(Properties.Settings.Default.myconnectionstring)) { sqlcon.Open(); using(SqlCommand cmd = new SqlCommand("userlogs", sqlcon)) { cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.Add(new SqlParameter("@id", Main.userid)); cmd.Parameters.Add(new SqlParameter("@fullname", Main.passname)); cmd.Parameters.Add(new SqlParameter("@activitydetails", txtfullname.Text)); cmd.Parameters.Add(new SqlParameter("@userform", 1)); // 直接传递DateTime对象 cmd.Parameters.Add(new SqlParameter("@datelog", DateTime.Now)); cmd.ExecuteNonQuery(); } } }
内容的提问来源于stack exchange,提问作者Jansen Malaggay
相关产品推荐
相关产品推荐

