C#Winform窗体应用程序中查询数据库时报错问题分析
|
admin
2025年1月19日 14:42
本文热度 233
|
执行长时间任务查询数据库,那么可能会出现一个问题:在执行长时间任务的过程中,如果点击了进度条中的“取消”按钮,此时可以停止程序执行查询数据库的任务,但是如果再次执行该任务时,可能会报错:“连接未关闭,连接的当前状态为打开”。下面以一个简单的示例来看看出现上面所述问题的原因所在。首先,用access创建一个数据库文件database.mdb,并保存在C#项目的bin\debug文件夹中。创建一个数据表TestData,在数据表里设置一个自增字段、一个姓名字段,一个年龄字段。仍然使用上一篇文章中所创建窗体和类,只把DataOperate.cs这个类修改一下,改成以下的代码,用于模拟耗时的数据库读取任务:using System;
using System.ComponentModel;
using System.Data.OleDb;
using System.Data;
using System.IO;
using System.Threading;
namespace Test
{
internal class DataOperate
{
private static String StrConn;
private static OleDbConnection conn;
private static OleDbCommand sc;
public void operating(BackgroundWorker worker)
{
ConnectDatabase();
for (int i = 0; i < 10; i++)
{
Thread.Sleep(1000); //暂停1秒,模拟耗时的数据库操作
operate("insert into TestData(姓名,年龄) values('全栈开发的码农',3)");
worker.ReportProgress(i*100/10);
}
}
private void ConnectDatabase()
{
//连接数据库
StrConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Directory.GetCurrentDirectory() + @"\database.mdb; " + "Persist Security Info=True;Jet OLEDB:Database Password=123456";
try
{
conn = new OleDbConnection(StrConn);
}
catch (System.Data.SqlClient.SqlException ex)
{
throw new Exception(ex.Message);
}
}
private void operate(String strsql)//插入、删除、更新等数据库操作
{
conn.Open();
sc = new OleDbCommand();
sc.CommandText = strsql;
sc.Connection = conn;
Thread.Sleep(1000); //暂停1秒,模拟耗时的数据库操作
sc.ExecuteNonQuery();
conn.Close();
}
public void close() //关闭数据库连接
{
if (conn.State == ConnectionState.Open)
{
conn.Close();
conn.Dispose();
}
}
}
}
此时,点击主窗体中的“开始”按钮,开始执行任务,往数据库里的TestData数据表插入记录,程序运行正常。执行到一半的时候,点击进度条窗体中的“取消”按钮,此时任务被取消。此时,如果再次点击主窗体中的“开始”按钮,出现“连接未关闭”的报错。经分析,问题出现在OleDbConnection对象conn上,在DataOperate.cs类中,把OleDbConnection对象conn定义成static静态对象,这对于一般的数据库操作是没有问题的,因为每一个数据库执行方法中都有conn.open()和conn.close(),数据连接可以正常打开和正常关闭,而当使用了Backgroundworker对象进行进度报告时,中途突然中断数据库查询操作,那么会导致conn.close()无法正常执行,使得连接依然处于打开状态,下一次尝试再次连接时就出现了“连接未关闭”的报错。解决问题的最简单粗暴的方法就是把static删除,使conn成为一个普通的非静态变量即可。这是因为static对象在程序运行的全过程中只能有一个实例,第一次执行数据库操作时,它已经实例化,再次执行数据库操作时,也只能使用它,不能再次实例化,而它没有被正常关闭连接,所以再次尝试连接数据库时会出现“连接未关闭”的情况,而如果采用了非静态变量,那么就相当于给conn对象重新实例化,用一个全新的完全不同于此前的实例来操作数据库,这样就不会报错了。
阅读原文:原文链接
该文章在 2025/1/21 9:36:19 编辑过