【问题标题】:How to Send Backup or Restore command to Command Window如何将备份或还原命令发送到命令行窗口
【发布时间】:2017-02-20 21:52:06
【问题描述】:

好的,我想我需要澄清一下我之前忘记提及的帖子。我在 Visual Studio 2010 中的“测试应用程序”有一个 SQL Server 2008 R2 EXPRESS 数据库。但是,该数据库不是来自独立 SQL Server Express 安装的。相反,数据文件,即 .mdf 和 .ldf 来自 VS“Project\Add New Item\Data\Service-based Database”中的选择。因此我的“BkUp_SMO.mdf”数据文件。

我不确定以上内容是否有所不同,但我尝试了多个使用 Microsoft.SqlServer.Management 对象 SMO 的示例,但均未成功。我已添加所需的 .DLL,即 Microsoft.SqlServer.ConnectionInfo、Microsoft.SqlServer.Management.Sdk.Sfc、Microsoft.SqlServer.Smo、Microsoft.SqlServer.SmoExtended。

在我的代码中,我对 Microsoft.SqlServer.Management.Common 和 Microsoft.SqlServer.Management.Smo 都有“使用”语句。 我什至为 System.Deployment.Application 添加了一个“使用”,以便使用 String dbPath = ApplicationDeployment.CurrentDeployment.DataDirectory; 为返回 DB 和日志文件所在的 ClickOnce 部署文件夹的路径设置一个字符串值;

除了下面引用的文章之外,我还尝试了另一篇文章中的示例,即“用 C# 备份 SQL 数据库”Backing up an SQL Database in C#

不能在 Visual Studio 创建的 SQL 数据库上执行备份和还原吗?

我用 C# 编写了一个测试应用程序,目的是通过命令行发送 SQL Server 备份或还原命令。我的一些代码基于一篇标题为:从命令行备份和还原 SQL Server 数据库

的文章

Backup and Restore Your SQL Server Database from the Command Line

完整的应用程序将是一个 user_App,我不希望最终用户必须打开命令窗口并输入任何内容,因此我试图通过 C# 代码发送所需的命令,如下所示。我的问题是,代码无异常运行,CMD 窗口打开和关闭,但没有对我的 SQL Server 2008 R2 数据文件 (.mdf) 进行任何备份。

请提出我在我的代码中缺少的内容,或更好的方法来完成此任务。 另外,完整备份是否也会自动备份日志文件 (.ldf)?

First code attempt
private void btnChoose_Click(object sender, EventArgs e)
{
    if (optBkupCMD.Checked)
    {
        StringBuilder bkup = new StringBuilder();
        bkup.Append("SqlCmd -E -S ");
        bkup.Append(Environment.MachineName);//servername appears to be same as computer name.
        bkup.Append(" –Q “BACKUP DATABASE [BkUp_SMO.mdf] TO DISK=’C:\\Backups\\BkUp_SMO.bak'”");
        string theBackup = bkup.ToString();

    using (Process process = new Process())
    {
        process.StartInfo.FileName = "cmd.exe";
        process.StartInfo.RedirectStandardInput = true;
        process.StartInfo.RedirectStandardOutput = true;
        process.StartInfo.CreateNoWindow = false;
        process.StartInfo.UseShellExecute = false;
        process.StartInfo.Arguments = @"/C";
        process.Start();
        process.StandardInput.WriteLine(theBackup);
        process.StandardInput.Flush();
        process.StandardInput.Close();
        process.WaitForExit();
        Console.WriteLine(process.StandardOutput.ReadToEnd());
    }
else if (optRestoreCMD.Checked)
{
    StringBuilder rstr = new StringBuilder();
    rstr.Append("SqlCmd -E -S ");
    rstr.Append(Environment.MachineName);
    rstr.Append(" –Q “RESTORE DATABASE [BkUp_SMO.mdf] FROM DISK=’C:\\Backups\\BkUp_SMO.bak'”");
    string restore = rstr.ToString();

    using (Process process = new Process())
    {
        process.StartInfo.FileName = "cmd.exe";
        process.StartInfo.RedirectStandardInput = true;
        process.StartInfo.RedirectStandardOutput = true;
        process.StartInfo.CreateNoWindow = false;
        process.StartInfo.UseShellExecute = false;
        process.StartInfo.Arguments = @"/C";
        process.Start();
        process.StandardInput.WriteLine(restore);
        process.StandardInput.Flush();
        process.StandardInput.Close();
        process.WaitForExit();
        Console.WriteLine(process.StandardOutput.ReadToEnd());
    }
}

}

My 2nd code attempt.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using Microsoft.Win32;
using System.Deployment.Application;
using System.Diagnostics;
using System.IO;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Common;

namespace DB_Bkup_using_SMO
{
    public partial class Bkup_in_CSharp : Form
    {
        public Bkup_in_CSharp()
        {
            InitializeComponent();
        }

    private void btnBkViaCsharp_Click(object sender, EventArgs e)
    {
        string filePath = ApplicationDeployment.CurrentDeployment.DataDirectory;
        BackupDatabase(filePath);
    }

    private void btnRestViaCsharp_Click(object sender, EventArgs e)
    {
        string filePath = ApplicationDeployment.CurrentDeployment.DataDirectory;
        RestoreDatabase(filePath);
    }

    ///<summary>
    ///Backup a whole database to the specified file.
    ///</summary>
    ///<remarks>
    ///The database must not be in use when backing up.
    ///The folder holding the file must have appropriate permissions given
    ///</remarks>
    ///<param name="backupFile">Full path to file to hold the backup</param>
    public static void BackupDatabase(string backupFile)
    {
        try
        {
            ServerConnection con = new ServerConnection(@"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\BkUp_SMO.mdf;Integrated Security=True;User Instance=True");

            Server server = new Server(con);
            Backup source = new Backup();
            source.Database = "BkUp_SMO.mdf";
            source.Action = BackupActionType.Database;

            source.LogTruncation = BackupTruncateLogType.Truncate;
            BackupDeviceItem destination = new BackupDeviceItem(backupFile, DeviceType.File);
            source.Devices.Add(destination);

            source.SqlBackup(server);
            con.Disconnect();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message + " " + ex.InnerException);
        }
    }

    ///<summary>
    ///Restore a whole database from a backup file.
    ///</summary>
    ///<remarks>
    ///The database must be in use when backing up.
    ///The folder holding the file must have appropriate permissions given.
    ///</remarks>
    ///<param name="backupFile">Full path to file to holding the backup</param>
    public static void RestoreDatabase(string backupFile)
    {
        try
        {
            ServerConnection con = new ServerConnection(@"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\BkUp_SMO.mdf;Integrated Security=True;User Instance=True");

            Server server = new Server(con);
            Restore destination = new Restore();
            destination.Database = "BkUp_SMO.mdf";
            destination.Action = RestoreActionType.Database;
            destination.Action = RestoreActionType.Log;
            BackupDeviceItem source = new BackupDeviceItem(backupFile, DeviceType.File);
            destination.Devices.Add(source);
            destination.ReplaceDatabase = true;
            destination.SqlRestore(server);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message + " " + ex.InnerException);
        }

    }
}
}

【问题讨论】:

  • 您是否必须“显示”黑色命令行界面?如果没有,有一种常见的更简单的备份方式,就像我的一样。
  • 你好凯李。不,我不必查看命令窗口。不过,它必须为最终用户提供一种轻松执行备份恢复的方法。请分享您的方法或代码示例。

标签: c# sql-server-2008 command-line-interface


【解决方案1】:

这是我用来备份 SQL Server 2008 R2 的代码。

如果您尝试搜索,这种基本示例代码在很多地方。

只需尝试,但无需将其标记为答案,因为这里有很多。

string masterdb_ConnectionString = string.Format(@"Data Source={0};Initial Catalog=Master;Connect Timeout=79;Encrypt=False;TrustServerCertificate=True;ApplicationIntent=ReadWrite;MultiSubnetFailover=False;Integrated Security=True;", System.Environment.MachineName);

using (SqlConnection masterdbConn = new SqlConnection())
{
    masterdbConn.ConnectionString = mastedb_rConnectionString;
    masterdbConn.Open();

    using (SqlCommand multiuser_rollback_dbcomm = new SqlCommand())
    {
        multiuser_rollback_dbcomm.Connection = masterdbConn;
        multiuser_rollback_dbcomm.CommandText= @"ALTER DATABASE yourdbname SET MULTI_USER WITH ROLLBACK IMMEDIATE";
        multiuser_rollback_dbcomm.CommandTimeout = 79;

        multiuser_rollback_dbcomm.ExecuteNonQuery();
    }
    masterdbConn.Close();
}

SqlConnection.ClearAllPools();

string yourdb_ConnectionString= "connectionstring for yourdb here";

using (SqlConnection backupConn = new SqlConnection())
{
    backupConn.ConnectionString = yourdb_ConnectionString;
    backupConn.Open();

    using (SqlCommand backupcomm = new SqlCommand())
    {
        backupcomm.Connection = backupConn;
        backupcomm.CommandText = string.Format(@"BACKUP DATABASE yourdbname TO DISK='c:\yourdbname.bak'", DateTime.Today.ToString("yyyy/MM/dd"));
        backupcomm.CommandTimeout = 79;

        backupcomm.ExecuteNonQuery();
    }
    backupConn.Close();
}

更新- 客户(用户)的计算机上会安装 SQL Server 2008 R2 吗?

您已经在使用“Integrated Security=True”,这意味着使用此连接字符串的用户将拥有作为管理员的所有(完全)权限。连接主数据库显然是没有问题的。

关于 IMMEDIATE ROLLBACK,这会完成所有未完成的事务,就像“在我们备份之前从数据库中放手”一样。换句话说,在我们关闭餐厅之前,如果我们不宣布这家餐厅将要关闭,如果我们突然关闭餐厅,即使餐厅关闭,一些顾客可能仍然有食物。

看看,ALTER DATABASE IMMEDIATE ROLLBACK, Technet

此示例在第一个 ALTER DATABASE 语句中使用终止选项 WITH ROLLBACK IMMEDIATE。所有未完成的事务都将被回滚,并且与 AdventureWorks2008R2 示例数据库的任何其他连接都将立即断开。

最后,您似乎正在尝试使用 SMO。我经历了几天的困难,但最终失败了,走了另一条路。

【讨论】:

  • 你好,凯。我不太了解您的代码示例。看起来它正在连接到 MASTER 数据库,而不是我的数据库。根据我的阅读,这可能需要提升用户凭据。另外,不理解您对“multiuser_rollback”或 ALTER db 语句的引用。这是一个分布式的“单用户”最终用户应用程序。请参阅我上面关于这是 Visual Studio 创建的 SQL Express 数据文件而不是独立的 SQL Express 安装的编辑。谢谢
  • @CodeMann,请参阅我的更新答案。抱歉,由于我的重要工作,我没有太多时间..希望这有帮助..
  • Kay,我尝试了您的代码示例,在执行代码时,它抛出了以下异常:建立与 SQL Server 的连接时发生网络相关或特定于实例的错误。服务器未找到或无法访问。验证实例名称是否正确以及 SQL Server 是否配置为允许远程连接。 (提供者:命名管道提供者,错误:40 - 无法打开与 SQL Server 的连接) System.ComponentModel.Win32Exception (0x80004005):系统找不到指定的文件。
  • P.S. SQL Server 不会安装在用户的计算机上。这是一个具有基于服务的数据库的分布式应用程序,即 .mdf、_log.ldf。尽管在 ClickOnce Prerequisites 下列出了“SQL Server 2008 Express”,但这并不是使用 ManagementStudio 安装的独立 SQL Server。相反,Visual Studio 创建了数据文件。
  • @CodeMann,服务器机器的正确名称和实例名称很简单,但在连接字符串中仍然很重要。请尝试搜索有关此内容。从远程服务器备份数据库在我看来似乎非常复杂和困难,但看看stackoverflow.com/questions/3942207/…
猜你喜欢
  • 2011-06-14
  • 1970-01-01
  • 2020-04-10
  • 1970-01-01
  • 2010-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-16
相关资源
最近更新 更多