SMO: restoring to a different DB
Asked Answered
C

2

4

I've read a dozen different blogs, as well as reading through the msdn examples and they just aren't working for me.

Ultimately what I'm trying to do is automate moving a DB from our production instance to our dev instance, or the other direction.

The approach I've taken is thus:

  1. backup/restore to a temp DB
  2. detach temp DB
  3. copy mdf and ldf files to the other instance
  4. reattach.

I'm stuck on 1 and I cannot understand why. Everything I've read claims this should be working.

NOTE: I've set dbName to the db I want to restore to. I have also set restore.Database = dbName, where restore is an instance of the Restore class in the smo namespace.

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);

This is the exception I'm getting:

The file 'D:\MSSQL.MIQ_Dev\MSSQL.2\MSSQL\Data\MIQDesign2Detach.mdf' cannot be overwritten. It is being used by database 'MIQDesignTest2'.
File 'MIQDesign' cannot be restored to 'D:\MSSQL.MIQ_Dev\MSSQL.2\MSSQL\Data\MIQDesign2Detach.mdf'. Use WITH MOVE to identify a valid location for the file.
The file 'D:\MSSQL.MIQ_Dev\MSSQL.2\MSSQL\Data\MIQDesign2Detach.ldf' cannot be overwritten. It is being used by database 'MIQDesignTest2'.
File 'MIQDesign_log' cannot be restored to 'D:\MSSQL.MIQ_Dev\MSSQL.2\MSSQL\Data\MIQDesign2Detach.ldf'. Use WITH MOVE to identify a valid location for the file.
Problems were identified while planning for the RESTORE statement. Previous messages provide details.
RESTORE DATABASE is terminating abnormally.

Why is this trying to overwrite the original mdf? Isn't the RelocateFiles stuff supposed to specify that you want it being saved to a different physical filename?

Cucumber answered 26/10, 2009 at 20:26 Comment(0)
L
-3

I ran into a similar problem and I found this solution to be quite helpful.

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

Leann answered 23/11, 2010 at 21:34 Comment(2)
Thank you Birbal, I was never able to solve the issue and I've since moved onto bigger and better things, but I'll definitely keep this in mind if I ever find myself automating things via SMO again :)Cucumber
Dead link. This is the problem with LINK ONLY answers. You should have posted information to the answer, and linked to the article as an "in depth" recommendation if you was not going to copy it over.Bough
S
5

It is works.

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;
    }
}
Snakemouth answered 28/1, 2014 at 16:26 Comment(0)
L
-3

I ran into a similar problem and I found this solution to be quite helpful.

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

Leann answered 23/11, 2010 at 21:34 Comment(2)
Thank you Birbal, I was never able to solve the issue and I've since moved onto bigger and better things, but I'll definitely keep this in mind if I ever find myself automating things via SMO again :)Cucumber
Dead link. This is the problem with LINK ONLY answers. You should have posted information to the answer, and linked to the article as an "in depth" recommendation if you was not going to copy it over.Bough

© 2022 - 2024 — McMap. All rights reserved.