最近在做项目时遇到了这个问题,使用DataSource绑定重新数据源时,DataGridview的UI显示不能立即更新,
加了断点调试单步跟踪执行可以看到数据确实更新并且UI也更新显示了,但是取消断点执行确还是无法立即更
新UI显示。
//Form1代码: //数据库对象 private AccessDB data = new AccessDB(); //由于涉及到多线程添加数据,所以使用了委托 delegate void refreshHandle(); public void RefreshData() { if (dataGridView1.InvokeRequired) { dataGridView1.Invoke( new refreshHandle(RefreshData)); } else { dataGridView1.DataSource = data.getAllData(); } }//AccessDB类 public DataTable getAllData() { try { olecmd = new OleDbCommand("select * from UserInfo ", oledbCon); OleDbDataAdapter adp = new OleDbDataAdapter(olecmd); DataTable dt = new DataTable(); adp.Fill(dt); return dt; } catch (OleDbException ex) { EndConnect(); MessageBox.Show(ex.Message); return null; } finally { }}
//Mainform添加数据按钮的实现 private void button1_Click(object sender, EventArgs e) { data.openConect(); string olecmd = string.Format("insert into UserInfo values('{0}','{1}','{2}')", "123", "hello world", "222"); data.ExecCmd(olecmd); form1.RefreshData(); data.closeConnect(); }
从主窗体打开窗体后,单击添加数据按钮(往数据库添加数据,调用form1的刷新函数),form1窗体不能立即更新显示,但是数据确实添加进去了,右击form1弹出菜单刷新后(即再次调用RefreshData()函数),
可以看到数据确实更新了。为什么不能立即更新呢,纠结了好长时间。
单击form1添加数据按钮调用同样的函数确可以立即刷新显示,难道是跨窗体的原因???
找了一通资料和人讨论终于找到解决方案,原因在于:
在调用form1.RefreshData()函数前,我调用了data.openConnect()函数打开了数据库的连接。
而关键在于OleDbDataAdapter类的构造和使用,MSDN是这样讲的:
如果在使用OleDbDataAdapter之前,改数据库的连接已经代开则必须显式关闭,问题的症结所在!
果然关闭了数据库连接之后,添加数据可以立即更新显示了。
修改后: (注意语句修改的顺序)
//Mainform添加数据按钮的实现 private void button1_Click(object sender, EventArgs e) { data.openConect(); string olecmd = string.Format("insert into UserInfo values('{0}','{1}','{2}')", "123", "hello world", "222"); data.ExecCmd(olecmd); data.closeConnect(); form1.RefreshData(); }
总结:
1.如果在使用OleDbDataAdapter之前某个其他对象在其他地方打开了数据库,忘了关闭,即使你下面这样使用;
dataGridView1.DataSource = new AccessDB().getAllData();通过重新构造一个数据库对象,没有打开数据库连接函数直接调用getAllData()函数,
数据虽然重新绑定了,但是UI还是不能立即显示,要想立即显示必须保证所有使用数据库的对象都已关闭数据库的连接。(使用跨窗体的情况)
2.如果本窗体自己添加的话,不存在上述问题(即使不关闭已打开的连接),但是还是建议按照MSDN的要求来,关闭所有对象已打开的数据库连接,无需打开数据库连接直接使用OleDbDataAdapter对象。