关闭C# WinForms应用时无法向MS Access插入超时日志
应用关闭时无法插入MS Access超时日志的解决方案
问题描述
使用Application.Exit()或this.Close()可正常关闭应用,但无法向MS Access数据库的tblLogs表插入用户超时日志。需求是关闭表单时,自动插入包含Log Time、STATUS、UserID、UserType的超时记录。尝试从LoginForm文本框获取用户ID和密码查询信息后调用RecordTimeOut方法插入日志,但未成功。
用户提供的代码
关闭按钮事件代码
private void btnCloseLight_Click(object sender, EventArgs e) { try { //For Getting data from Login Form LoginForm form1instance = new LoginForm(); string userId = form1instance.Form1userLoginTextBox; string password = form1instance.Form1passLoginTextBox; connection.Open(); cmd = new OleDbCommand("SELECT [UserID], [UserType] FROM tblUser WHERE UserID = @UserID AND Password = @Password", connection); cmd.Parameters.AddWithValue("@UserID", userId); cmd.Parameters.AddWithValue("@Password", password); OleDbDataReader reader = cmd.ExecuteReader(); if (reader.Read()) { string userID = reader["UserID"].ToString(); int userType = Convert.ToInt32(reader["UserType"]); //Inserting Time OUT to tblLogs RecordTimeOut(userID, userType); } } catch (Exception ex) { MessageBox.Show("Error: " + ex.Message); } finally { if (connection.State == ConnectionState.Open) connection.Close(); } } public void RecordTimeOut(string userId, int userType) { try { using (OleDbConnection insertConnection = new OleDbConnection(connectionString)) { string status = "TIME OUT"; insertConnection.Open(); cmd = new OleDbCommand("INSERT INTO tblLogs ([Log Time], [STATUS], [UserID], [UserType]) VALUES ([@Log Time], [@STATUS], [@UserID], [@UserType])", connection); cmd.Parameters.AddWithValue("@Log Time", DateTime.Now.ToString()); cmd.Parameters.AddWithValue("@STATUS", status); cmd.Parameters.AddWithValue("@UserID", userId); cmd.Parameters.Add("@UserType", OleDbType.Integer).Value = userType; cmd.ExecuteNonQuery(); } } catch (Exception ex) { MessageBox.Show("Error Inserting Log: " + ex.Message); } }
登录模块代码
#region LogIn public void OpenStudentForm() { //Close Login form this.Hide(); //Shows the New Forms StudentForm stuForm = new StudentForm(); stuForm.FormClosed += (s, args) => this.Close(); // Close the App is when this Form is Closed stuForm.Show(); } public void OpenInstructorForm() { //Close Login form this.Hide(); InstructorForm insForm = new InstructorForm(); insForm.FormClosed += (s, args) => this.Close(); // Close the App is when this Form is Closed insForm.Show(); } public void OpenSystemAdminForm() { //Close Login form this.Hide(); SystemAdminForm sysAdminForm = new SystemAdminForm(); sysAdminForm.FormClosed += (s, args) => this.Close(); // Close the App is when this Form is Closed sysAdminForm.Show(); } private void btnLogin_Click(object sender, EventArgs e) { string userIDLogin = userIdLoginTextBox.Texts; string passwordLogin = passwordLoginTextBox.Texts; try { connection.Open(); cmd = new OleDbCommand("SELECT [UserID], [UserType] FROM tblUser WHERE UserID = @UserID AND Password = @Password", connection); cmd.Parameters.AddWithValue("@UserID", userIDLogin); cmd.Parameters.AddWithValue("@Password", passwordLogin); OleDbDataReader reader = cmd.ExecuteReader(); if (reader.Read()) { string userID = reader["UserID"].ToString(); int userType= Convert.ToInt32(reader["UserType"]); //Inserting Login Info to tblLogs InsertLoginLog(userID, userType); switch (userType) { case 0: //Student OpenStudentForm(); break; case 1: //Instructor MessageBox.Show("Instructor"); OpenInstructorForm(); break; case 2: //System Admin MessageBox.Show("System Admin"); OpenSystemAdminForm(); break; default: MessageBox.Show("Unknown User Type"); break; } } else { MessageBox.Show("Invalid User ID or Password"); } } catch (Exception ex) { MessageBox.Show("Error: " + ex.Message); } finally { if (connection.State == ConnectionState.Open) connection.Close(); } } public void InsertLoginLog(string userID, int userType) { try { using (OleDbConnection insertConnection = new OleDbConnection(connectionString)) { string status = "TIME IN"; insertConnection.Open(); cmd = new OleDbCommand("INSERT INTO tblLogs ([Log Time], [STATUS], [UserID], [UserType]) VALUES ([@Log Time], [@STATUS], [@UserID], [@UserType])", connection); cmd.Parameters.AddWithValue("@Log Time", DateTime.Now.ToString()); cmd.Parameters.AddWithValue("@STATUS", status); cmd.Parameters.AddWithValue("@UserID", userID); cmd.Parameters.Add("@UserType", OleDbType.Integer).Value = userType; cmd.ExecuteNonQuery(); } } catch (Exception ex) { MessageBox.Show("Error inserting Log: " + ex.Message); } } #endregion
问题根源分析
- 错误获取登录用户信息:关闭按钮事件中新建了
LoginForm实例,这是一个全新的空表单,并非用户登录时使用的实例,因此文本框内容为空,查询不到用户数据,RecordTimeOut方法不会被执行。 - 数据库连接与命令不匹配:
RecordTimeOut和InsertLoginLog方法中,创建OleDbCommand时使用了全局的connection对象,而非using块内的insertConnection,导致命令与连接不匹配,无法执行插入操作。 - 参数格式错误:SQL语句中参数名被方括号包裹,OleDb对参数的解析是按顺序匹配而非名称,多余的方括号会导致参数识别失败;同时将
DateTime.Now转为字符串插入,可能引发日期格式兼容问题。
修复方案
1. 保存登录用户的全局信息
在LoginForm中添加静态变量存储登录用户信息,避免关闭时重新查询:
// LoginForm中添加静态变量 public static string CurrentUserID { get; private set; } public static int CurrentUserType { get; private set; }
在登录成功的逻辑中赋值:
if (reader.Read()) { CurrentUserID = reader["UserID"].ToString(); CurrentUserType = Convert.ToInt32(reader["UserType"]); InsertLoginLog(CurrentUserID, CurrentUserType); // 后续打开对应表单逻辑 }
2. 修复数据库插入方法
修正RecordTimeOut方法,确保使用当前using块内的连接,参数写法正确,直接传递DateTime类型:
public void RecordTimeOut() { try { using (OleDbConnection insertConnection = new OleDbConnection(connectionString)) { string status = "TIME OUT"; insertConnection.Open(); string sql = "INSERT INTO tblLogs ([Log Time], [STATUS], [UserID], [UserType]) VALUES (@LogTime, @Status, @UserID, @UserType)"; using (OleDbCommand cmd = new OleDbCommand(sql, insertConnection)) { cmd.Parameters.AddWithValue("@LogTime", DateTime.Now); cmd.Parameters.AddWithValue("@Status", status); cmd.Parameters.AddWithValue("@UserID", LoginForm.CurrentUserID); cmd.Parameters.Add("@UserType", OleDbType.Integer).Value = LoginForm.CurrentUserType; cmd.ExecuteNonQuery(); } } } catch (Exception ex) { MessageBox.Show("Error Inserting Log: " + ex.Message); } }
同理修正InsertLoginLog方法,确保连接和参数匹配。
3. 修改关闭按钮事件逻辑
直接使用全局存储的用户信息调用RecordTimeOut:
private void btnCloseLight_Click(object sender, EventArgs e) { try { if (!string.IsNullOrEmpty(LoginForm.CurrentUserID)) { RecordTimeOut(); } } catch (Exception ex) { MessageBox.Show("Error: " + ex.Message); } finally { Application.Exit(); } }
4. 处理表单关闭事件
在各功能表单的FormClosing事件中确保日志插入完成后再关闭:
private void StudentForm_FormClosing(object sender, FormClosingEventArgs e) { LoginForm loginForm = new LoginForm(); loginForm.RecordTimeOut(); e.Cancel = false; }
内容的提问来源于stack exchange,提问作者Aguni
相关产品推荐
相关产品推荐

