SMO:恢复到不同的DB

时间:2009-10-26 20:26:14

标签: smo

我已经阅读了十几个不同的博客,以及通过msdn示例阅读,他们只是不适合我。

最终我要做的是自动将数据库从我们的生产实例移动到我们的开发实例,或者另一个方向。

我采取的方法是:

  1. 备份/恢复到临时数据库
  2. detach temp DB
  3. 将mdf和ldf文件复制到另一个实例
  4. 重新连接。
  5. 我被困在1上,我无法理解为什么。我读到的所有内容都声称这应该有效。

    注意:我已将dbName设置为要恢复到的数据库。我还设置了restore.Database = dbName,其中restoreRestore命名空间中smo类的实例。

    mdf.LogicalFileName = dbName;
    mdf.PhysicalFileName = String.Format(@"{0}\{1}.mdf", server.Information.MasterDBPath, dbName);
    ldf.LogicalFileName = dbName + "_log";
    ldf.PhysicalFileName = String.Format(@"{0}\{1}.ldf", server.Information.MasterDBPath, dbName);
    
    restore.RelocateFiles.Add(mdf);
    restore.RelocateFiles.Add(ldf);
    restore.SqlRestore(server);
    

    这是我得到的例外:

      

    无法覆盖文件'D:\ MSSQL.MIQ_Dev \ MSSQL.2 \ MSSQL \ Data \ MIQDesign2Detach.mdf'。数据库'MIQDesignTest2'正在使用它   文件'MIQDesign'无法恢复为'D:\ MSSQL.MIQ_Dev \ MSSQL.2 \ MSSQL \ Data \ MIQDesign2Detach.mdf'。使用WITH MOVE标识文件的有效位置   无法覆盖文件'D:\ MSSQL.MIQ_Dev \ MSSQL.2 \ MSSQL \ Data \ MIQDesign2Detach.ldf'。数据库'MIQDesignTest2'正在使用它   文件'MIQDesign_log'无法恢复为'D:\ MSSQL.MIQ_Dev \ MSSQL.2 \ MSSQL \ Data \ MIQDesign2Detach.ldf'。使用WITH MOVE标识文件的有效位置   在规划RESTORE语句时发现了问题。以前的消息提供了详细信息   RESTORE DATABASE异常终止。

    为什么要尝试覆盖原来的mdf? RelocateFiles内容是否应该指定您希望将其保存为不同的物理文件名?

2 个答案:

答案 0 :(得分:5)

这是有效的。

public class DatabaseManager
{
    public Action<int, string> OnSqlBackupPercentComplete;
    public Action<int, string> OnSqlRestorePercentComplete;
    public Action<SqlError> OnSqlBackupComplete;
    public Action<SqlError> OnSqlRestoreComplete;

    public bool IsConnected { get; private set; }

    private ServerConnection _connection;

    public void Connect(string userName, string password, string serverName, bool useInteratedLogin)
    {
        if (useInteratedLogin)
        {
            var sqlCon = new SqlConnection(string.Format("Data Source={0}; Integrated Security=True; Connection Timeout=5", serverName));
            _connection = new ServerConnection(sqlCon);
            _connection.Connect();
            IsConnected = true;
        }
        else
        {
            _connection = new ServerConnection(serverName, userName, password);
            _connection.ConnectTimeout = 5000;
            _connection.Connect();
            IsConnected = true;
        }

    }

    public void BackupDatabase(string databaseName, string destinationPath)
    {
        var sqlServer = new Server(_connection);


        databaseName = databaseName.Replace("[", "").Replace("]", "");
        var sqlBackup = new Backup
            {
                Action = BackupActionType.Database,
                BackupSetDescription = "ArchiveDataBase:" + DateTime.Now.ToShortDateString(),
                BackupSetName = "Archive",
                Database = databaseName
            };

        var deviceItem = new BackupDeviceItem(destinationPath, DeviceType.File);

        sqlBackup.Initialize = true;
        sqlBackup.Checksum = true;
        sqlBackup.ContinueAfterError = true;

        sqlBackup.Devices.Add(deviceItem);
        sqlBackup.Incremental = false;
        sqlBackup.ExpirationDate = DateTime.Now.AddDays(3);

        sqlBackup.LogTruncation = BackupTruncateLogType.Truncate;
        sqlBackup.PercentCompleteNotification = 10;
        sqlBackup.PercentComplete += (sender, e) => OnSqlBackupPercentComplete(e.Percent, e.Message);
        sqlBackup.Complete += (sender, e) => OnSqlBackupComplete(e.Error);
        sqlBackup.FormatMedia = false;
        sqlBackup.SqlBackup(sqlServer);


    }

    public DatabaseCollection GetDatabasesList()
    {
        if (IsConnected)
        {
            var sqlServer = new Server(_connection);
            return sqlServer.Databases;
        }
        return null;
    }



    public void RestoreDatabase(string databaseName, string filePath)
    {
        var sqlServer = new Server(_connection);

        databaseName = databaseName.Replace("[", "").Replace("]", "");

        var sqlRestore = new Restore();
        sqlRestore.PercentCompleteNotification = 10;
        sqlRestore.PercentComplete += (sender, e) => OnSqlRestorePercentComplete(e.Percent, e.Message);
        sqlRestore.Complete += (sender, e) => OnSqlRestoreComplete(e.Error);

        var deviceItem = new BackupDeviceItem(filePath, DeviceType.File);
        sqlRestore.Devices.Add(deviceItem);
        sqlRestore.Database = databaseName;

        DataTable dtFileList = sqlRestore.ReadFileList(sqlServer);

        int lastIndexOf = dtFileList.Rows[1][1].ToString().LastIndexOf(@"\");
        string physicalName = dtFileList.Rows[1][1].ToString().Substring(0, lastIndexOf + 1);
        string dbLogicalName = dtFileList.Rows[0][0].ToString();
        string dbPhysicalName = physicalName + databaseName + ".mdf";
        string logLogicalName = dtFileList.Rows[1][0].ToString();
        string logPhysicalName = physicalName + databaseName + "_log.ldf";
        sqlRestore.RelocateFiles.Add(new RelocateFile(dbLogicalName, dbPhysicalName));
        sqlRestore.RelocateFiles.Add(new RelocateFile(logLogicalName, logPhysicalName));

        sqlServer.KillAllProcesses(sqlRestore.Database);

        Database db = sqlServer.Databases[databaseName];
        if (db != null)
        {
            db.DatabaseOptions.UserAccess = DatabaseUserAccess.Single;
            db.Alter(TerminationClause.RollbackTransactionsImmediately);
            sqlServer.DetachDatabase(sqlRestore.Database, false);
        }

        sqlRestore.Action = RestoreActionType.Database;
        sqlRestore.ReplaceDatabase = true;

        sqlRestore.SqlRestore(sqlServer);
        db = sqlServer.Databases[databaseName];
        db.SetOnline();
        sqlServer.Refresh();
        db.DatabaseOptions.UserAccess = DatabaseUserAccess.Multiple;
    }

    public void Disconnect()
    {
        if (IsConnected)
            _connection.Disconnect();

        IsConnected = false;
    }
}

答案 1 :(得分:-1)

我遇到了类似的问题,我发现这个解决方案非常有用。

看看 - http://www.eggheadcafe.com/software/aspnet/32188436/smorestore-database-name-change.aspx