现在的位置: 首页 > 综合 > 正文

备份SQL数据库

2013年09月14日 ⁄ 综合 ⁄ 共 17085字 ⁄ 字号 评论关闭

从project菜单中选择add reference----COM---------
Microsoft DTSPackage Object Library与Microsoft SQLDMO Object Library

打开对象浏览器,展开Interop.SQLDMO,现实属性与方法
使用对象SQLServer,Backup,BackupDevices,Backupdevice,QueryResults
程序太大,留mail我发给你吧。
shaokui.wang@cn.abb.com

try
   {
    SQLDMO.Backup oBackup = new SQLDMO.BackupClass();
    SQLDMO.SQLServer oSQLServer = new SQLDMO.SQLServerClass();
    oSQLServer.LoginSecure = false;
    oSQLServer.Connect("localhost", "sa", "1234");
    oBackup.Action = SQLDMO.SQLDMO_BACKUP_TYPE.SQLDMOBackup_Database;
    oBackup.Database = "Northwind";
    oBackup.Files = @"d:/Northwind.bak";
    oBackup.BackupSetName = "Northwind";
    oBackup.BackupSetDescription = "数据库备份";
    oBackup.Initialize = true;
    oBackup.SQLBackup(oSQLServer);
   }
   catch
   {
    throw;
   }

 

   try
   {
    SQLDMO.Restore oRestore = new SQLDMO.RestoreClass();
    SQLDMO.SQLServer oSQLServer = new SQLDMO.SQLServerClass();
    oSQLServer.LoginSecure = false;
    oSQLServer.Connect("wellserver", "sa", "well");
    oRestore.Action = SQLDMO.SQLDMO_RESTORE_TYPE.SQLDMORestore_Database;
    oRestore.Database = "czwelldb";
    oRestore.Files = @"d:/czwelldb.bak";
    oRestore.FileNumber = 1;
    oRestore.ReplaceDatabase = true;
    oRestore.SQLRestore(oSQLServer);
   }
   catch
   {
    throw;
   }

主  题:  最近由于工作需要,写了个数据库的备份与恢复,贴出来与大家分享。
 
作  者:  zhangqy (zhangqy) 
信 誉 值:  90
所属论坛:  .NET技术 C#
问题点数:  0
回复次数:  3
发表时间:  2004-02-26 12:28:54
  
 
  
 
最近由于工作需要,写了个数据库的备份与恢复,贴出来与大家分享。
准备工作:
1.先在项目中添加backfile.xml文件,根结点为<root></root>.
2.打开库master,新建存储过程,旨在杀掉其它用户的访问。其中@dbname为备份数据库的名称(以上实例为hdnjw,根据你的数据库名改。)
  CREATE  PROCEDURE killspid  @dbname  varchar(20)
as
begin
declare  @sql  nvarchar(500),@temp varchar(1000)
declare  @spid  int
set  @sql='declare  getspid  cursor  for
select  spid  from  master..sysprocesses  where  dbid=db_id('''+@dbname+''')' 
exec  (@sql)  
open  getspid  
fetch  next  from  getspid  into  @spid
while  @@fetch_status <> -1
begin
  set @temp='kill  '+rtrim(@spid)
  exec(@temp)
fetch  next  from  getspid  into  @spid
end
close  getspid
deallocate  getspid
end
GO
3.打开hdnjw,新建存储过程.
  CREATE PROCEDURE  BackDataBase  @backPath varchar(100)
AS 
        BACKUP DATABASE hdnjw TO DISK = @backPath  WITH NOINIT
GO   
4.根椐我的经验,最好添加一个能访问,操作数据表的用户。
以下为备份与恢复的源程序.

//备份数据库(hdnjw),备份文件存于../../databackup/下

  private void btnBack_Click(object sender, System.EventArgs e)
  {
   SqlDataBase.DbBase conn = new SqlDataBase.DbBase();
   DateTime dt = DateTime.Now ;
   string sPath = dt.Year.ToString() + dt.Month.ToString() + dt.Day.ToString() + dt.Hour.ToString() + dt.Minute.ToString() + dt.Second.ToString() ;
   System.IO.DirectoryInfo oD = new DirectoryInfo( Server.MapPath( "../../DataBackUp/" ) ) ;
   string sLinkName =  "../../DataBackUp/" + sPath ;
   //判断是否存在此目录,否则新建目录
   if ( !oD.Exists )
    oD.Create() ;
   conn.BackDataBase( Server.MapPath( sLinkName ) ) ;
   //XML格式为<root><backfile><id></id><title></title><createtime></createtime><linkname></linkname></backfile></root>
            XmlDocument xmlDoc = new XmlDocument() ;
   xmlDoc.Load( Server.MapPath( "backfile.xml" ) ) ;
   //获取最后一个节点的递一个元素的值(ID) + 1 成为新的元素的ID值
   XmlNode node = xmlDoc.LastChild.LastChild ;
   int intID = 1 ;
   if ( node != null )
     intID += Convert.ToInt32( node.FirstChild.InnerText ) ;
 
   //添加一个backfile节点
   XmlElement elem = xmlDoc.CreateElement( "backfile" ) ;
   
   XmlElement elem1 ;
   XmlText xmlTxt ;

   //添加backfile节点的id元素
   elem1 = xmlDoc.CreateElement( "id" ) ;
   xmlTxt = xmlDoc.CreateTextNode( intID.ToString() ) ;         //文件名
   elem1.AppendChild( xmlTxt ) ;
   elem.AppendChild( elem1 ) ;

            //添加backfile节点的filename元素
   elem1 = xmlDoc.CreateElement( "title" ) ;
   xmlTxt = xmlDoc.CreateTextNode( txtTitle.Text.Trim() ) ;         //文件名
   elem1.AppendChild( xmlTxt ) ;
   elem.AppendChild( elem1 ) ;
   
   //备份时间
   elem1 = xmlDoc.CreateElement( "createtime" ) ;
   xmlTxt = xmlDoc.CreateTextNode( DateTime.Now.ToString( "yyyy-MM-dd" ) ) ;
   elem1.AppendChild( xmlTxt ) ;
   elem.AppendChild( elem1 ) ;
   
   //文件路径
   elem1 = xmlDoc.CreateElement( "linkname" ) ;
   xmlTxt = xmlDoc.CreateTextNode( DateTime.Now.ToString( sPath ) ) ;
   elem1.AppendChild( xmlTxt ) ;
   elem.AppendChild( elem1 ) ;

   //添加操作,方便DataGrid取数据
   elem1 = xmlDoc.CreateElement( "dosomething" ) ;
   xmlTxt = xmlDoc.CreateTextNode( "恢复" ) ;
   elem1.AppendChild( xmlTxt ) ;
   elem.AppendChild( elem1 ) ;
   
   //添加backfile节点
   xmlDoc.DocumentElement.AppendChild( elem ) ;
   xmlDoc.Save( Server.MapPath( "backfile.xml" ) ) ;

   Response.Write( "<script language=javascript>alert('已成功备份!');var win =window.open('index.aspx','main');</script>"  ) ;
 
  }

//恢复数据库

private void BackUpDataBase ( string strID )
{
 string strPath = "" ;
 XmlDataDocument dom=new XmlDataDocument();
 dom.Load ( Server.MapPath(  "backfile.xml" ) ) ;
 XmlElement root = dom.DocumentElement;
 //查找id.value=Request["id"]的节点
 XmlNode node = root.SelectSingleNode( "//backfile[id='"+strID +"']");
 if( node != null )         //找到了
 {
  //文件路径节点
  strPath = node.ChildNodes.Item(3).InnerText ;  
 }
 if ( strPath != "" )
 {
  CommonOperation.Operation Common = new CommonOperation.Operation();
  SqlDataBase.DbBase conn = new SqlDataBase.DbBase();
  //以数据库管理员(sa)恢复数据,首先杀掉所有用户进程
  conn.ConnStr = System.Configuration.ConfigurationSettings.AppSettings["DbConnAdmin"] ;
  conn.DynamicStoredProcedure( "killspid" ) ;
  SqlParameter sp_temp1;
  sp_temp1 = conn.m_Command.Parameters.Add("@dbname",SqlDbType.VarChar,200);
  sp_temp1.Direction = ParameterDirection.Input;
  sp_temp1.Value = "hdnjw" ;
  try
  {
   string FilePath = Server.MapPath( "../../DataBackUp/" + strPath ) ;
   conn.ExecuteSqlForDynamic() ;
   conn.ExecuteSql( "alter database hdnjw set RESTRICTED_USER  with rollback immediate" ) ;//恢复数据时禁止除SA外的任何人访问库
   string sRestroe = "Restore DataBase hdnjw From disk='"+ FilePath +"' " ;
   conn.ExecuteSql( sRestroe ) ;
   conn.ExecuteSql( "alter database hdnjw set MULTI_USER  with rollback immediate" ) ;//充许访问库
   conn.ConnStr = System.Configuration.ConfigurationSettings.AppSettings["DbConn"] ;
   Response.Write( "<script language=javascript>alert('成功恢复数据!');window.close();</script>" ) ;
  }
  catch ( System.Exception ee )
  {
   Common.MsgBox( this,ee.ToString() ) ;
  }
  finally
  {
   conn.Close() ;
  }
 }
  }
 
 
 
 
  使用存储过程,根据需要传递相应参数即可

create proc BackupDB
@dbname sysname='',  --要备份的数据库名称,不指定则备份当前数据库
@bkpath nvarchar(260)='', --备份文件的存放目录,不指定则使用SQL默认的备份目录
@bkfname nvarchar(260)='', --备份文件名,文件名中可以用/DBNAME/代表数据库名,/DATE/代表日期,/TIME/代表时间
@bktype nvarchar(10)='DB', --备份类型:'DB'备份数据库,'DF' 差异备份,'LOG' 日志备份
@appendfile bit=1  --追加/覆盖备份文件
as
 declare @sql varchar(8000)
 if isnull(@dbname,'')='' set @dbname=db_name()
 if isnull(@bkpath,'')='' set @bkpath=dbo.f_getdbpath(null)
 if isnull(@bkfname,'')='' set @bkfname='/DBNAME/_/DATE/_/TIME/.BAK'
 set @bkfname=replace(replace(replace(@bkfname,'/DBNAME/',@dbname)
  ,'/DATE/',convert(varchar,getdate(),112))
  ,'/TIME/',replace(convert(varchar,getdate(),108),':',''))
 set @sql='backup '+case @bktype when 'LOG' then 'log ' else 'database ' end +@dbname
  +' to disk='''+@bkpath+@bkfname
  +''' with '+case @bktype when 'DF' then 'DIFFERENTIAL,' else '' end
  +case @appendfile when 1 then 'NOINIT' else 'INIT' end
 print @sql
 exec(@sql)

GO

 

////////////////////////////////////////////////////////////
SQL SERVER备份:
sql="backup database mydb to disk='"+nowpath+"//数据备份文件(不要删除).dll"+"' with format,name='Full Backup of TradeDb/SQL'";
   try
   {
    SqlCommand  cmd = new SqlCommand(sql, conn);
    cmd.ExecuteNonQuery();
    MessageBox.Show("成功备份数据!备份记录为:"+nowpath+"//数据备份文件(不要删除).dll"," 成功了!", MessageBoxButtons.OK, MessageBoxIcon.Information );
   }
   catch(Exception err)
   {
    MessageBox.Show("出现错误,请与作者联系!"+err.ToString() ,"出错了!",MessageBoxButtons.OK ,MessageBoxIcon.Question  );
     
   }
   finally
   {
    conn.Close();
    this.Close();
    
   }

 

 

还原:
 由于可能数据库被其它进程打开,所以写的一段SQL SERVER的代码,在MASTER中存为一个存储过程:
create  proc  killspid  (@dbname  varchar(20)) 
as 
begin 
declare  @sql  nvarchar(500) 
declare  @spid  int 
set  @sql='declare  getspid  cursor  for   
select  spid  from  sysprocesses  where  dbid=db_id('''+@dbname+''')' 
exec  (@sql) 
open  getspid 
fetch  next  from  getspid  into  @spid 
while  @@fetch_status  <  >-1 
begin 
exec('kill  '+@spid
fetch  next  from  getspid  into  @spid 
end 
close  getspid 
deallocate  getspid 
end 
然后,在C#代码里:
try
   {
   string nowpath=Application.StartupPath;
   
   //进入master
     sql="use master";
     SqlCommand cmd = new SqlCommand(sql, conn);
     cmd.ExecuteNonQuery();
   try
   {
    //执行存储过程杀掉其它进程
    sql="exec  killspid 'mydb'";
    cmd = new SqlCommand(sql, conn);
    cmd.ExecuteNonQuery();
   }
   
   finally
   { 
 
    
                FileInfo backupdata = new FileInfo(nowpath+"//数据备份文件(不要删除).dll");
    if (backupdata.Exists)
    {

     sql="restore database mydb from disk='"+nowpath+"//数据备份文件(不要删除).dll"+"' with recovery";
     cmd = new SqlCommand(sql, conn);
     cmd.ExecuteNonQuery();
     MessageBox.Show("成功恢复数据!从"+nowpath+"//数据备份文件(不要删除).dll 中恢复"," 成功了!", MessageBoxButtons.OK, MessageBoxIcon.Information );
    }
    else
    {
    MessageBox.Show("你可能以前没有备份过数据库!数据备份文件(不要删除).dll 不存在!"," 错误!", MessageBoxButtons.OK, MessageBoxIcon.Information );
    }
   }
    
   }
   catch(Exception err)
   {
    MessageBox.Show("出现错误,请对数据库端进行正确配置!"+err.ToString() ,"出错了!",MessageBoxButtons.OK ,MessageBoxIcon.Question  );
     
   }
   finally
   {
    conn.Close();
    this.Close();
    
   }

/************************************************************************************************/
//可参考下面代码。代码有待修改的地方,使用sql语句进行数据备份,恢复
/// <summary>
        /// 备份数据库
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
  private void _ButtonBackUp_Click(object sender, System.EventArgs e)
  {
   dbConnSet frm = new dbConnSet();//获得数据库sa帐号,密码
   frm.ShowDialog();
   if(frm.isNormal==false)
    return;
   this.Cursor = Cursors.WaitCursor;
   string _DBSource  = "(local)";
   string _DBCatalog = "master";
   string _DBUser    = frm.textBoxDBUser.Text;
   string _DBPass    = frm.textBoxDBPas.Text;
   string m_ConnectionStr   = "Provider=SQLOLEDB;Password="+_DBPass+";User ID="+_DBUser+";Initial Catalog="+_DBCatalog+";Data Source="+_DBSource+";Connect Timeout=5;";  
   OleDbConnection _Conn = new OleDbConnection(m_ConnectionStr);           
   try
   {
    _Conn.Open();
    NetBee.Controls.FolderBrowserEX.FolderBrowser _SaveFileDialog = new NetBee.Controls.FolderBrowserEX.FolderBrowser();         //保存的文件目录路径      
    _SaveFileDialog.Description = "请选择备份保存的目录";
    if(_SaveFileDialog.ShowDialog()==DialogResult.OK)
    {
      
     string _FolderPath = _SaveFileDialog.DirectoryPath;             
     string[] DBName = {Cs.PubObject.dbName};
     for(int i=0;i<DBName.Length;i++)
     {
                          
      string _DBName   = DBName[i];
      OleDbCommand _Comm = new OleDbCommand("",_Conn);
      //执行数据库备份命令
      _Comm.CommandText = "BACKUP DATABASE "+_DBName+" TO DISK = '"+ _SaveFileDialog.DirectoryPath+@"/"+_DBName +".bak'";
      _Comm.ExecuteNonQuery();     
     } 
     this.Cursor = Cursors.Arrow;
     _Conn.Close();
     MessageBox.Show("备份数据成功!","提示",MessageBoxButtons.OK,MessageBoxIcon.Information);
     
       
    }
                this.Cursor = Cursors.Arrow;

   }
   catch(System.Exception error)
   {
    this.Cursor = Cursors.Arrow;
    MessageBox.Show("异常:"+error.Message,"提示",MessageBoxButtons.OK,MessageBoxIcon.Error);
   }
   this.Cursor = Cursors.Arrow;
  }

  #endregion

  #region 恢复数据库
  /// <summary>
  /// 恢复数据库
  /// </summary>
  /// <param name="sender"></param>
  /// <param name="e"></param>
  private void _ButtonRestory_Click(object sender, System.EventArgs e)
  {
   dbConnSet frm = new dbConnSet();
   frm.ShowDialog();
   if(frm.isNormal==false)
    return;
   if(MessageBox.Show("该操作将数据覆盖!!/n/n如果选择[是],将原来的数据覆盖/n/n如果选择[否],将退出安装","提示",MessageBoxButtons.YesNo,MessageBoxIcon.Question)==DialogResult.No)
    return;
   if(MessageBox.Show("请在此确认,该操作不能恢复!!/n/n如果选择[是],将原来的数据覆盖/n/n如果选择[否],将退出安装","提示",MessageBoxButtons.YesNo,MessageBoxIcon.Warning)==DialogResult.No)
    return;
   this.Cursor = Cursors.WaitCursor;
   string _DBSource  = "(local)";
   string _DBCatalog = "master";
   string _DBUser    = frm.textBoxDBUser.Text;
   string _DBPass    = frm.textBoxDBPas.Text;
   string m_ConnectionStr   = "Provider=SQLOLEDB;Password="+_DBPass+";User ID="+_DBUser+";Initial Catalog="+_DBCatalog+";Data Source="+_DBSource+";Connect Timeout=5;"; 
   OleDbConnection _Conn = new OleDbConnection(m_ConnectionStr);           
   try
   {
    _Conn.Open(); 
    NetBee.Controls.FolderBrowserEX.FolderBrowser _SaveFileDialog = new NetBee.Controls.FolderBrowserEX.FolderBrowser();               
    _SaveFileDialog.Description = "请要恢复的数据目录";
    if(_SaveFileDialog.ShowDialog()==DialogResult.OK)
    {
      
     string _FolderPath = _SaveFileDialog.DirectoryPath;             
     string[] DBName = {Cs.PubObject.dbName};
     for(int i=0;i<DBName.Length;i++)
     {
      string _DBName   = DBName[i];  
      string _BakFilePath = _SaveFileDialog.DirectoryPath+@"/"+DBName[i]+@".bak";
      OleDbCommand _Comm = new OleDbCommand("restore filelistonly from disk='"+_FolderPath+@"/"+_DBName+@".bak'",_Conn);//获得原来的逻辑名称以及物理路径
      OleDbDataReader _Reader = null;
      _Reader = _Comm.ExecuteReader();
      string[]  _LogName = new string[2];//获得逻辑名称
      string[]  _PhiPath = new string[2];//获得物理路径
      int j = 0;
      while(_Reader.Read())
      {
       _LogName[j] = (string)_Reader.GetValue(0);
       _PhiPath[j] = (string)_Reader.GetValue(1);
       j = j+1;
      }
      _Reader.Close();
      
      //执行数据库恢复脚本
      _Comm = new OleDbCommand("",_Conn);
      _Comm.CommandText ="RESTORE DATABASE [" + _DBName + "]   FROM DISK = '" + _BakFilePath + "' With Move '"+ _LogName[0] +
       "' TO '" +_PhiPath[0]+ "',  Move '" + _LogName[1] + "' TO '" + _PhiPath[1]+ "'";
      _Comm.ExecuteNonQuery();     
      
     }  
     this.Cursor = Cursors.Arrow;
     MessageBox.Show("数据恢复成功!","提示",MessageBoxButtons.OK,MessageBoxIcon.Information);
     _Conn.Close();
       
    }
                this.Cursor = Cursors.Arrow;

   }
   catch(System.Exception error)
   {
    this.Cursor = Cursors.Arrow;
    MessageBox.Show("异常:"+error.Message,"错误",MessageBoxButtons.OK,MessageBoxIcon.Error);
   }    
  }
  #endregion

 

/******************************************************sqldmo

  private void Form1_Load(object sender, System.EventArgs e)
  {
   try
   {
    //get all available SQL Servers    
    sqlServers = sqlApp.ListAvailableSQLServers();
    for(int i=0;i<sqlServers.Count;i++)
    {
     object srv = sqlServers.Item( i + 1);
     if(srv != null)
     {
      this.cboServers.Items.Add(srv);      
     }
    }
    if(this.cboServers.Items.Count > 0)
     this.cboServers.SelectedIndex = 0;
    else
     this.cboServers.Text = "<No available SQL Servers>";

   }
   catch(Exception err)
   {
    MessageBox.Show(err.Message,"Error");
   }
  }

  //Get Tables
  private void linkLabel2_LinkClicked(object sender, System.Windows.Forms.LinkLabelLinkClickedEventArgs e)
  {
   try
   {
    this.Cursor = Cursors.WaitCursor;
    this.lstObjects.Items.Clear();
    this.cboDatabase.Items.Clear();    
   
    SQLDMO.SQLServer srv = new SQLDMO.SQLServerClass();    
    srv.Connect(this.cboServers.SelectedItem.ToString(),this.txtUser.Text,this.txtPassword.Text);

    foreach(SQLDMO.Database db in srv.Databases)
    {
     if(db.Name!=null)
      this.cboDatabase.Items.Add(db.Name);
    }
    this.cboDatabase.Sorted = true;
    if(this.cboDatabase.Items.Count >0)
    {
     this.cboDatabase.SelectedIndex = 0;
     this.cboDatabase.Enabled = true;
     this.groupBox1.Enabled = true;
    }
    else
    {
     this.groupBox1.Enabled = false;
     this.cboDatabase.Enabled = false;
     this.cboDatabase.Text = "<No databases found>";
    }
    this.Cursor = Cursors.Default;
   }
   catch(Exception err)
   {
    this.Cursor = Cursors.Default;
    MessageBox.Show(err.Message,"Error");
   }
  }
  

  //Get stored procedures
  private void linkLabel1_LinkClicked(object sender, System.Windows.Forms.LinkLabelLinkClickedEventArgs e)
  {
   this.Cursor = Cursors.WaitCursor;
   SQLDMO.SQLServer srv = new SQLDMO.SQLServerClass();    
   srv.Connect(this.cboServers.SelectedItem.ToString(),this.txtUser.Text,this.txtPassword.Text);
   for(int i=0;i<srv.Databases.Count;i++)
   {
    if(srv.Databases.Item(i+1,"dbo").Name == this.cboDatabase.SelectedItem.ToString())
    {
     SQLDMO._Database db= srv.Databases.Item(i+1,"dbo");
     this.lstObjects.Items.Clear();
     for(int j=0;j<db.Tables.Count;j++)
     {
      this.lstObjects.Items.Add(db.Tables.Item(j+1,"dbo").Name);
     }
     this.Cursor = Cursors.Default;
     return;
    }
   }
   this.Cursor = Cursors.Default;
  }
  
  // Get Views
  private void linkLabel3_LinkClicked(object sender, System.Windows.Forms.LinkLabelLinkClickedEventArgs e)
  {
   this.Cursor = Cursors.WaitCursor;
   SQLDMO.SQLServer srv = new SQLDMO.SQLServerClass();    
   srv.Connect(this.cboServers.SelectedItem.ToString(),this.txtUser.Text,this.txtPassword.Text);
   for(int i=0;i<srv.Databases.Count;i++)
   {
    if(srv.Databases.Item(i+1,"dbo").Name == this.cboDatabase.SelectedItem.ToString())
    {
     SQLDMO._Database db= srv.Databases.Item(i+1,"dbo");
     this.lstObjects.Items.Clear();
     
     for(int j=0;j<db.StoredProcedures.Count;j++)
     {
      this.lstObjects.Items.Add(db.StoredProcedures.Item(j+1,"dbo").Name);
     }
     this.Cursor = Cursors.Default;
     return;
    }
   }
   this.Cursor = Cursors.Default;
  }

  private void linkLabel4_LinkClicked(object sender, System.Windows.Forms.LinkLabelLinkClickedEventArgs e)
  {
   this.Cursor = Cursors.WaitCursor;
   SQLDMO.SQLServer srv = new SQLDMO.SQLServerClass();    
   srv.Connect(this.cboServers.SelectedText,this.txtUser.Text,this.txtPassword.Text);
   for(int i=0;i<srv.Databases.Count;i++)
   {
    if(srv.Databases.Item(i+1,"dbo").Name == this.cboDatabase.SelectedItem.ToString())
    {
     SQLDMO._Database db= srv.Databases.Item(i+1,"dbo");
     this.lstObjects.Items.Clear();
     for(int j=0;j<db.Views.Count;j++)
     {
      this.lstObjects.Items.Add(db.Views.Item(j+1,"dbo").Name);
     }
     this.Cursor = Cursors.Default;
     return;
    }
   }
   this.Cursor = Cursors.Default;
  }

  private void cboDatabase_SelectedIndexChanged(object sender, System.EventArgs e)
  {
   this.lstObjects.Items.Clear();
  }

  
 }

抱歉!评论已关闭.