Setting single user mode to restore backup

旧街凉风 提交于 2019-12-14 03:48:00

问题


I have the following function:

public void RestoreDatabase(String databaseName, String backUpFile, 
                            String serverName, String userName, String password)
{
    SqlConnection.ClearAllPools();
    ServerConnection connection = new ServerConnection
                                          (serverName, userName, password);
    Server sqlServer = new Server(connection);
    Restore rstDatabase = new Restore();
    rstDatabase.Action = RestoreActionType.Database;
    rstDatabase.Database = databaseName;
    BackupDeviceItem bkpDevice = new BackupDeviceItem
                                         (backUpFile, DeviceType.File);
    rstDatabase.Devices.Add(bkpDevice);
    rstDatabase.ReplaceDatabase = true;
    rstDatabase.SqlRestore(sqlServer);
}

I was trying to set the DB to single user mode first, before restoring the backup. I tried this code:

        private string singleUserCmd = "alter database db-name set SINGLE_USER";
        private string multiUserCmd = "alter database db-name  set MULTI_USER";

        private void SetSingleUser(bool singleUser, 
                                   SqlConnectionStringBuilder csb)
        {
            string v;
            if (singleUser)
            {
                v = singleUserCmd.Replace("db-name", csb.InitialCatalog);
            }
            else
            {
                v = multiUserCmd.Replace("db-name", csb.InitialCatalog);
            }
            SqlCommand cmd = new SqlCommand(v, new SqlConnection
                                                     (csb.ToString()));
            try
            {
                cmd.Connection.Open();
                cmd.ExecuteNonQuery();
            }
            finally
            {
                cmd.Connection.Close();
            }
        }

The problem seems to be that single user mode is for that connection, preventing anyone else from doing anything. I need it to be for the connection that restores the backup.


回答1:


The restore would need to occur on the connection which placed the DB into single user mode, so why not make your SetSingleUser function return the opened SqlConnection it executed on and then have your Restore code take in and use the same opened connection.

private string singleUserCmd = "alter database db-name set SINGLE_USER";
private string multiUserCmd = "alter database db-name  set MULTI_USER";

private SqlConnection SetSingleUser(bool singleUser, SqlConnectionStringBuilder csb)
{
    string v;
    if (singleUser)
    {
        v = singleUserCmd.Replace("db-name", csb.InitialCatalog);
    }
    else
    {
        v = multiUserCmd.Replace("db-name", csb.InitialCatalog);
    }
    SqlConnection connection = new SqlConnection(csb.ToString());
    SqlCommand cmd = new SqlCommand(v, connection);

        cmd.Connection.Open();
        cmd.ExecuteNonQuery();

    return connection;
}



回答2:


duckworth's answer is quite correct. but you can also do it in this way:

using System;
using System.Data.SqlClient;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo;

public class DatabaseRestoreHelper
{
    private const string _SingleUserCmd = "ALTER DATABASE {0} SET SINGLE_USER WITH ROLLBACK IMMEDIATE";
    private const string _MultiUserCmd = "ALTER DATABASE {0} SET MULTI_USER";

    public static void RestoreDatabase(string connectionString, string backupSetPath, bool verify)
    {
        SqlConnectionStringBuilder cb = new SqlConnectionStringBuilder(connectionString);
        string database = cb.InitialCatalog;

        cb.InitialCatalog = "master";

        SqlConnection sqlConnection = new SqlConnection(cb.ConnectionString);
        ServerConnection serverConnection = new ServerConnection(sqlConnection);

        try
        {
            //Make Database Single User
            serverConnection.ExecuteNonQuery(String.Format(_SingleUserCmd, database));

            Server server = new Server(serverConnection);
            Restore restore = new Restore();

            BackupDeviceItem destination = new BackupDeviceItem(backupSetPath, DeviceType.File);

            restore.Action = RestoreActionType.Database;
            restore.Database = database;
            restore.Devices.Add(destination);
            restore.ReplaceDatabase = true;

            if (verify)
            {
                string errorMessage;

                if (!restore.SqlVerify(server, out errorMessage))
                {
                    throw new Exception(errorMessage);
                }
            }

            restore.SqlRestore(server);
        }
        catch
        {
            throw;
        }
        finally
        {
            //Make Database Multi User
            serverConnection.ExecuteNonQuery(String.Format(_MultiUserCmd, database));
            serverConnection.Disconnect();
        }
    }

    public static void BackupDatabase(string connectionString, string backupSetPath, bool verify)
    {
        SqlConnectionStringBuilder cb = new SqlConnectionStringBuilder(connectionString);
        string database = cb.InitialCatalog;

        cb.InitialCatalog = "master";

        SqlConnection sqlConnection = new SqlConnection(cb.ConnectionString);
        ServerConnection serverConnection = new ServerConnection(sqlConnection);

        try
        {
            //Make Database Single User
            serverConnection.ExecuteNonQuery(String.Format(_SingleUserCmd, database));

            Server server = new Server(serverConnection);
            Backup backup = new Backup();

            BackupDeviceItem destination = new BackupDeviceItem(backupSetPath, DeviceType.File);

            backup.Action = BackupActionType.Database;
            backup.Database = database;
            backup.Devices.Add(destination);
            backup.SqlBackup(server);

            if (verify)
            {
                Restore restore = new Restore();

                restore.Action = RestoreActionType.Database;
                restore.Database = database;
                restore.Devices.Add(destination);
                restore.ReplaceDatabase = true;

                string errorMessage;

                if (!restore.SqlVerify(server, out errorMessage))
                {
                    throw new Exception(errorMessage);
                }
            }
        }
        catch
        {
            throw;
        }
        finally
        {
            //Make Database Multi User
            serverConnection.ExecuteNonQuery(String.Format(_MultiUserCmd, database));
            serverConnection.Disconnect();
        }
    }
}


来源:https://stackoverflow.com/questions/1674179/setting-single-user-mode-to-restore-backup

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!