异步备份和还原数据库:C#.NET发现之旅
2010-06-25 10:14
495 查看
信息系统是数据密集型的,数据的套帐,备份,还原是客户最希望有的功能,这一节课就讨论下C/S系统下数据库的异步备份和还原,B/S系统的数据备份和还原和这个类似。
既然是异步,首先会想到使用多线程技术。.NET平台提供了一整套的线程处理技术,使用线程的好处是,可以让一个线程做一件事情,多个线程之间根据时间片机制抢夺CPU和I/O资源,UI线程用于绘制界面,保证界面永远对客户的响应,而工作线程用于计算工作。
除了从头开发线程外,.NET也提供了一个封装好的线程组件BackgroundWorker,该组件让您能够在应用程序的主要 UI 线程以外的其他线程上异步(“在后台”)执行耗时的操作。比如耗时耗资源的常用操作如下:
· 图像下载
· Web 服务调用
· 文件下载和上载(包括点对点应用程序)
· 复杂的本地计算
· 数据库事务
· 本地磁盘访问(相对于内存访问来说其速度很慢)
类似这样的操作可能导致用户界面在操作运行时挂起。如果需要用户界面的响应却遇到与此类操作关联的长时间延迟,BackgroundWorker组件可以提供一种方便的解决方案。若要使用 BackgroundWorker,只需要告诉该组件要在后台执行的耗时的辅助方法,然后调用 RunWorkerAsync 方法。在辅助方法以异步方式运行的同时,您的调用线程继续正常运行。该方法运行完毕,BackgroundWorker激发 RunWorkerCompleted 事件(可选择包含操作结果)向调用线程发出警报。
“组件”选项卡的“工具箱”中提供了 BackgroundWorker组件。VS2005,VS2008, VS2010都有这个组件,如下图:
若要向窗体添加 BackgroundWorker,请将 BackgroundWorker组件拖到窗体上即可。
若要启动异步操作,请使用 RunWorkerAsync 方法。RunWorkerAsync 采用一个可选的 object 参数,可以使用该参数将变量传递给辅助方法。BackgroundWorker类公开 DoWork 事件,您的辅助线程通过 DoWork 事件处理程序附加到该事件。
BackgroundWorker包含三个主要的事件:
1,DoWork 事件
调用 RunWorkerAsync 方法时将引发此事件。在此,您就可以启动操作来执行可能很耗时的工作。
2, RunWorkerCompleted 事件
DoWork事件处理程序返回时将引发此事件。如果操作成功完成,并且其结果在 DoWork事件处理程序中进行了分配,则可以通过RunWorkerCompletedEventArgs.Result属性访问该结果。
3, ProgressChanged 事件
调用 ReportProgress 方法时将引发此事件。ProgressChanged事件向用户报告异步操作的进度
熟悉了组建用法后,开始做异步的数据库备份和还原
一,异步数据库备份,界面如下:
点击开始备份按钮,选择一个文件夹保存备份文件
然后开始备份,线程会不停的汇报它自己执行的进度,用一个进度条来接受线程的进度,这个是通过ProgressChanged 事件完成的。
当备份完成后,线程会通知系统,它已经返回。如果中间线程出现执行错误,通过程序来捕获。这个是通过RunWorkerCompleted 事件来完成的,而备份任务是通过DoWork 事件来完成的。
异步备份数据库的代码如下:
二,异步还原数据库
和备份类似,这里不再讲解,代码如下:
既然是异步,首先会想到使用多线程技术。.NET平台提供了一整套的线程处理技术,使用线程的好处是,可以让一个线程做一件事情,多个线程之间根据时间片机制抢夺CPU和I/O资源,UI线程用于绘制界面,保证界面永远对客户的响应,而工作线程用于计算工作。
除了从头开发线程外,.NET也提供了一个封装好的线程组件BackgroundWorker,该组件让您能够在应用程序的主要 UI 线程以外的其他线程上异步(“在后台”)执行耗时的操作。比如耗时耗资源的常用操作如下:
· 图像下载
· Web 服务调用
· 文件下载和上载(包括点对点应用程序)
· 复杂的本地计算
· 数据库事务
· 本地磁盘访问(相对于内存访问来说其速度很慢)
类似这样的操作可能导致用户界面在操作运行时挂起。如果需要用户界面的响应却遇到与此类操作关联的长时间延迟,BackgroundWorker组件可以提供一种方便的解决方案。若要使用 BackgroundWorker,只需要告诉该组件要在后台执行的耗时的辅助方法,然后调用 RunWorkerAsync 方法。在辅助方法以异步方式运行的同时,您的调用线程继续正常运行。该方法运行完毕,BackgroundWorker激发 RunWorkerCompleted 事件(可选择包含操作结果)向调用线程发出警报。
“组件”选项卡的“工具箱”中提供了 BackgroundWorker组件。VS2005,VS2008, VS2010都有这个组件,如下图:
若要向窗体添加 BackgroundWorker,请将 BackgroundWorker组件拖到窗体上即可。
若要启动异步操作,请使用 RunWorkerAsync 方法。RunWorkerAsync 采用一个可选的 object 参数,可以使用该参数将变量传递给辅助方法。BackgroundWorker类公开 DoWork 事件,您的辅助线程通过 DoWork 事件处理程序附加到该事件。
BackgroundWorker包含三个主要的事件:
1,DoWork 事件
调用 RunWorkerAsync 方法时将引发此事件。在此,您就可以启动操作来执行可能很耗时的工作。
2, RunWorkerCompleted 事件
DoWork事件处理程序返回时将引发此事件。如果操作成功完成,并且其结果在 DoWork事件处理程序中进行了分配,则可以通过RunWorkerCompletedEventArgs.Result属性访问该结果。
3, ProgressChanged 事件
调用 ReportProgress 方法时将引发此事件。ProgressChanged事件向用户报告异步操作的进度
熟悉了组建用法后,开始做异步的数据库备份和还原
一,异步数据库备份,界面如下:
点击开始备份按钮,选择一个文件夹保存备份文件
然后开始备份,线程会不停的汇报它自己执行的进度,用一个进度条来接受线程的进度,这个是通过ProgressChanged 事件完成的。
当备份完成后,线程会通知系统,它已经返回。如果中间线程出现执行错误,通过程序来捕获。这个是通过RunWorkerCompleted 事件来完成的,而备份任务是通过DoWork 事件来完成的。
异步备份数据库的代码如下:
//启动备份 private void btnBackUp_Click(object sender, EventArgs e) { try { SaveFileDialog sfd = new SaveFileDialog(); sfd.Title = "请选择备份保存的目录"; sfd.Filter = "(*.Bak)|*.Bak;|(All Files)|*.*"; if (sfd.ShowDialog() == DialogResult.OK && sfd.FileName != string.Empty) { string filePath = sfd.FileName; //启动异步备份,开始执行DoWork事件 this.backgroundWorker1.RunWorkerAsync(new string[] { filePath, "InstallationsManager" }); } } catch (System.Exception ex) { MessageBox.Show("异常:" + ex.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Error); } } //备份数据库 private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { try { using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["LongXiConnectionString"].ConnectionString)) { con.Open(); //汇报进度 this.backgroundWorker1.ReportProgress(20); string[] args = (string[])e.Argument; string filePath = args[0]; SqlCommand cmd = new SqlCommand(); cmd.Connection = con; //备份数据库 cmd.CommandText = "use master;backup database " + args[1] + " to disk = '" + filePath + "' "; cmd.ExecuteNonQuery(); this.backgroundWorker1.ReportProgress(60); //线程完成时返回的信息 e.Result = "备份数据成功!"; //this.label5.Text = "aaaaaaaa"; //Control.CheckForIllegalCrossThreadCalls = false this.backgroundWorker1.ReportProgress(100); } } catch (System.Exception ex) { MessageBox.Show("异常:" + ex.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Error); } } //线程执行完成后的收尾工作 private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { try { if (e.Error != null) { MessageBox.Show("异常:" + e.Error.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Error); } else if (e.Cancelled) { MessageBox.Show("线程已经退出!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } else { //MessageBox.Show(e.Result.ToString(), "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); //向UI提示备份数据库成功 this.lblInfo.Text = e.Result.ToString(); } } catch (System.Exception ex) { MessageBox.Show("异常:" + ex.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Error); } } //向UI线程汇报进度,使进度条的值增加 private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) { try { this.pbarBackUp.Value = e.ProgressPercentage; } catch (System.Exception ex) { MessageBox.Show("异常:" + ex.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
二,异步还原数据库
和备份类似,这里不再讲解,代码如下:
//启动还原 private void btnRestore_Click(object sender, EventArgs e) { //第一次后悔药 if (MessageBox.Show("该操作将数据覆盖!如果选择[是],将原来的数据覆盖;如果选择[否],将取消恢复.", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No) return; //第二次后悔药 if (MessageBox.Show("请再次确认,该操作不能恢复!如果选择[是],将原来的数据覆盖;如果选择[否],将取消恢复.", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.No) return; //没得后悔药吃了,开始执行还原 try { OpenFileDialog ofd = new OpenFileDialog(); ofd.Title = "请选择要恢复的备份文件"; ofd.Filter = "(*.Bak)|*.Bak;|(All Files)|*.*"; if (ofd.ShowDialog() == DialogResult.OK && ofd.FileName != string.Empty) { string filePath = ofd.FileName; //启动异步还原,开始执行DoWork事件 this.backgroundWorker1.RunWorkerAsync(new string[] { filePath, "InstallationsManager" }); } } catch (System.Exception ex) { MessageBox.Show("异常:" + ex.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Error); } } //还原数据库 private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { this.backgroundWorker1.ReportProgress(30); using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["LongXiConnectionString"].ConnectionString)) { con.Open(); //汇报进度 this.backgroundWorker1.ReportProgress(20); Thread.Sleep(1000); string[] args = (string[])e.Argument; string filePath = args[0]; SqlCommand cmd = new SqlCommand(); this.backgroundWorker1.ReportProgress(30); Thread.Sleep(1000); this.backgroundWorker1.ReportProgress(60); cmd.Connection = con; //还原数据库 cmd.CommandText = "use master;alter database " + args[1] + " set offline with rollback immediate;restore database " + args[1] + " from disk = '" + filePath + "' with replace"; cmd.ExecuteNonQuery(); this.backgroundWorker1.ReportProgress(80); Thread.Sleep(1000); this.backgroundWorker1.ReportProgress(100); //线程完成时返回的信息 e.Result = "恢复数据成功!"; } } //汇报进度,使进度条的值增加 private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) { this.pbarRestore.Value = e.ProgressPercentage; } //线程执行完成后的收尾工作 private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (e.Error != null) { MessageBox.Show("异常:" + e.Error.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Error); } else if (e.Cancelled) { MessageBox.Show("线程已经退出!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } else { //MessageBox.Show(e.Result.ToString(), "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); //向UI提示恢复数据库成功 this.lblInfo.Text = e.Result.ToString(); } }
相关文章推荐
- 异步备份和还原数据库:.NET发现之旅(六)
- 异步备份和还原数据库:.NET发现之旅(六) 推荐
- c# .NET 进行数据库备份和还原
- asp.net(C#) 数据库备份还原 源码
- 数据库备份与还原c#.net实现
- 【原创】ASP.NET C# 对SQL/ACCESS 数据库的备份和还原函数
- 代码实现ASP.NET数据库的备份和还原
- Asp.net 不使用SQLDMO实现数据库备份和还原
- asp.net 数据库备份与还原
- asp.net和c#实现定时备份数据库(SQL Server2000)
- 数据库备份与还原的C#实现
- C#备份,还原数据库
- c# winform 实现对postgresql数据库的自动备份还原功能
- C# 窗体备份/还原数据库
- 【MySql】C#数据库备份与还原
- ASP.NET中使用代码来进行备份和还原数据库
- ASP.NET备份数据与还原数据,解决数据库正在使用的问题
- C#备份及还原数据库的实现
- C# 数据库备份及还原
- C#远程数据库备份还原