SMO: восстановление в другую БД

Я прочитал дюжину разных блогов, а также прочитал примеры msdn, и они просто не работают для меня.

В конечном счете, я пытаюсь автоматизировать перемещение БД из нашего производственного экземпляра в наш экземпляр разработки или в другом направлении.

Подход, который я выбрал, таков:

  1. резервное копирование/восстановление во временную БД
  2. отключить временную БД
  3. скопировать файлы mdf и ldf в другой экземпляр
  4. прикрепить.

Я застрял на 1, и я не могу понять, почему. Все, что я читал, утверждает, что это должно работать.

ПРИМЕЧАНИЕ. Я установил dbName для базы данных, которую хочу восстановить. Я также установил restore.Database = dbName, где restore — экземпляр класса Restore в пространстве имен 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 не должно указывать, что вы хотите, чтобы он был сохранен в другом физическом имени файла?


smo
person Fred    schedule 26.10.2009    source источник


Ответы (2)


Я столкнулся с подобной проблемой, и я нашел это решение весьма полезным.

Взгляните — http://www.eggheadcafe.com/software/aspnet/32188436/smorestore-database-name-change.aspx

person birbal81    schedule 23.11.2010
comment
Спасибо, Бирбал, мне так и не удалось решить эту проблему, и с тех пор я перешел к более крупным и лучшим вещам, но я обязательно буду помнить об этом, если когда-нибудь снова обнаружу, что автоматизирую вещи через SMO :) - person Fred; 26.11.2010
comment
Мертвая ссылка. Это проблема с ответами ТОЛЬКО ССЫЛКА. Вы должны были опубликовать информацию к ответу и дать ссылку на статью в качестве подробной рекомендации, если вы не собирались ее копировать. - person StarPilot; 15.07.2014

Это работает.

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;
    }
}
person Stanislav Glushak    schedule 28.01.2014