1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 异步备份和还原数据库:.NET发现之旅(六)

异步备份和还原数据库:.NET发现之旅(六)

时间:2020-12-30 10:01:36

相关推荐

异步备份和还原数据库:.NET发现之旅(六)

信息系统是数据密集型的,数据的套帐,备份,还原是客户最希望有的功能,这一节课就讨论下C/S系统下数据库的异步备份和还原,B/S系统的数据备份和还原和这个类似。

既然是异步,首先会想到使用多线程技术。.NET平台提供了一整套的线程处理技术,使用线程的好处是,可以让一个线程做一件事情,多个线程之间根据时间片机制抢夺CPU和I/O资源,UI线程用于绘制界面,保证界面永远对客户的响应,而工作线程用于计算工作。

除了从头开发线程外,.NET也提供了一个封装好的线程组件BackgroundWorker,该组件让您能够在应用程序的主要UI线程以外的其他线程上异步(“在后台”)执行耗时的操作。比如耗时耗资源的常用操作如下:

·图像下载

·Web服务调用

·文件下载和上载(包括点对点应用程序)

·复杂的本地计算

·数据库事务

·本地磁盘访问(相对于内存访问来说其速度很慢)

类似这样的操作可能导致用户界面在操作运行时挂起。如果需要用户界面的响应却遇到与此类操作关联的长时间延迟,BackgroundWorker组件可以提供一种方便的解决方案。若要使用BackgroundWorker,只需要告诉该组件要在后台执行的耗时的辅助方法,然后调用RunWorkerAsync方法。在辅助方法以异步方式运行的同时,您的调用线程继续正常运行。该方法运行完毕,BackgroundWorker激发RunWorkerCompleted事件(可选择包含操作结果)向调用线程发出警报。

“组件”选项卡的“工具箱”中提供了BackgroundWorker组件。VS,VS,VS都有这个组件,如下图:

若要向窗体添加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事件来完成的。

异步备份数据库的代码如下:

//启动备份 privatevoidbtnBackUp_Click(objectsender,EventArgse) { try { SaveFileDialogsfd=newSaveFileDialog(); sfd.Title="请选择备份保存的目录"; sfd.Filter="(*.Bak)|*.Bak;|(AllFiles)|*.*"; if(sfd.ShowDialog()==DialogResult.OK&&sfd.FileName!=string.Empty) { stringfilePath=sfd.FileName; //启动异步备份,开始执行DoWork事件 this.backgroundWorker1.RunWorkerAsync(newstring[]{filePath,"InstallationsManager"}); } } catch(System.Exceptionex) { MessageBox.Show("异常:"+ex.Message,"提示",MessageBoxButtons.OK,MessageBoxIcon.Error); } } //备份数据库 privatevoidbackgroundWorker1_DoWork(objectsender,DoWorkEventArgse) { try { using(SqlConnectioncon=newSqlConnection(ConfigurationManager.ConnectionStrings["LongXiConnectionString"].ConnectionString)) { con.Open(); //汇报进度 this.backgroundWorker1.ReportProgress(20); string[]args=(string[])e.Argument; stringfilePath=args[0]; SqlCommandcmd=newSqlCommand(); cmd.Connection=con; //备份数据库 mandText="usemaster;backupdatabase"+args[1]+"todisk='"+filePath+"'"; cmd.ExecuteNonQuery(); this.backgroundWorker1.ReportProgress(60); //线程完成时返回的信息 e.Result="备份数据成功!"; //this.label5.Text="aaaaaaaa";//Control.CheckForIllegalCrossThreadCalls=false this.backgroundWorker1.ReportProgress(100); } } catch(System.Exceptionex) { MessageBox.Show("异常:"+ex.Message,"提示",MessageBoxButtons.OK,MessageBoxIcon.Error); } } //线程执行完成后的收尾工作 privatevoidbackgroundWorker1_RunWorkerCompleted(objectsender,RunWorkerCompletedEventArgse) { try { if(e.Error!=null) { MessageBox.Show("异常:"+e.Error.Message,"提示",MessageBoxButtons.OK,MessageBoxIcon.Error); } elseif(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.Exceptionex) { MessageBox.Show("异常:"+ex.Message,"提示",MessageBoxButtons.OK,MessageBoxIcon.Error); } } //向UI线程汇报进度,使进度条的值增加 privatevoidbackgroundWorker1_ProgressChanged(objectsender,ProgressChangedEventArgse) { try { this.pbarBackUp.Value=e.ProgressPercentage; } catch(System.Exceptionex) { MessageBox.Show("异常:"+ex.Message,"提示",MessageBoxButtons.OK,MessageBoxIcon.Error); } }

二,异步还原数据库

和备份类似,这里不再讲解,代码如下:

//启动还原 privatevoidbtnRestore_Click(objectsender,EventArgse) { //第一次后悔药 if(MessageBox.Show("该操作将数据覆盖!如果选择[是],将原来的数据覆盖;如果选择[否],将取消恢复.","提示",MessageBoxButtons.YesNo,MessageBoxIcon.Question)==DialogResult.No) return; //第二次后悔药 if(MessageBox.Show("请再次确认,该操作不能恢复!如果选择[是],将原来的数据覆盖;如果选择[否],将取消恢复.","提示",MessageBoxButtons.YesNo,MessageBoxIcon.Warning)==DialogResult.No) return; //没得后悔药吃了,开始执行还原 try { OpenFileDialogofd=newOpenFileDialog(); ofd.Title="请选择要恢复的备份文件"; ofd.Filter="(*.Bak)|*.Bak;|(AllFiles)|*.*"; if(ofd.ShowDialog()==DialogResult.OK&&ofd.FileName!=string.Empty) { stringfilePath=ofd.FileName; //启动异步还原,开始执行DoWork事件 this.backgroundWorker1.RunWorkerAsync(newstring[]{filePath,"InstallationsManager"}); } } catch(System.Exceptionex) { MessageBox.Show("异常:"+ex.Message,"提示",MessageBoxButtons.OK,MessageBoxIcon.Error); } } //还原数据库 privatevoidbackgroundWorker1_DoWork(objectsender,DoWorkEventArgse) { this.backgroundWorker1.ReportProgress(30); using(SqlConnectioncon=newSqlConnection(ConfigurationManager.ConnectionStrings["LongXiConnectionString"].ConnectionString)) { con.Open(); //汇报进度 this.backgroundWorker1.ReportProgress(20); Thread.Sleep(1000); string[]args=(string[])e.Argument; stringfilePath=args[0]; SqlCommandcmd=newSqlCommand(); this.backgroundWorker1.ReportProgress(30); Thread.Sleep(1000); this.backgroundWorker1.ReportProgress(60); cmd.Connection=con; //还原数据库 mandText="usemaster;alterdatabase"+args[1]+"setofflinewithrollbackimmediate;restoredatabase"+args[1]+"fromdisk='"+filePath+"'withreplace"; cmd.ExecuteNonQuery(); this.backgroundWorker1.ReportProgress(80); Thread.Sleep(1000); this.backgroundWorker1.ReportProgress(100); //线程完成时返回的信息 e.Result="恢复数据成功!"; } } //汇报进度,使进度条的值增加 privatevoidbackgroundWorker1_ProgressChanged(objectsender,ProgressChangedEventArgse) { this.pbarRestore.Value=e.ProgressPercentage; } //线程执行完成后的收尾工作 privatevoidbackgroundWorker1_RunWorkerCompleted(objectsender,RunWorkerCompletedEventArgse) { if(e.Error!=null) { MessageBox.Show("异常:"+e.Error.Message,"提示",MessageBoxButtons.OK,MessageBoxIcon.Error); } elseif(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(); } }

本文转自terryli51CTO博客,原文链接:/terryli/335062,如需转载请自行联系原作者

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。