【问题标题】:How to restore a database from C#如何从 C# 恢复数据库
【发布时间】:2010-11-30 19:12:08
【问题描述】:

我有一个 SQL 2008 数据库。我正在运行一个支持该数据库的表单,然后尝试更新它。如果更新失败,想法是恢复该备份。这是我用来恢复备份的代码。

public void RestoreDatabase(String databaseName, String backUpFile, String serverName, String userName, String password)
{
    Restore sqlRestore = new Restore();
    BackupDeviceItem deviceItem = new BackupDeviceItem(backUpFile, DeviceType.File);
    sqlRestore.Devices.Add(deviceItem);
    sqlRestore.Database = databaseName;
    ServerConnection connection = new ServerConnection(serverName, userName, password);
    Server sqlServer = new Server(connection);
    sqlRestore.Action = RestoreActionType.Database;

    string logFile = System.IO.Path.GetDirectoryName(backUpFile);
    logFile = System.IO.Path.Combine(logFile, databaseName + "_Log.ldf");

    string dataFile = System.IO.Path.GetDirectoryName(backUpFile);
    dataFile = System.IO.Path.Combine(dataFile, databaseName + ".mdf");

    Database db = sqlServer.Databases[databaseName];
    RelocateFile rf = new RelocateFile(databaseName, dataFile);
    sqlRestore.RelocateFiles.Add(new RelocateFile(databaseName, dataFile));
    sqlRestore.RelocateFiles.Add(new RelocateFile(databaseName + "_log", logFile));
    sqlRestore.SqlRestore(sqlServer);
    db = sqlServer.Databases[databaseName];
    db.SetOnline();
    sqlServer.Refresh();
}

问题似乎是我选择的文件名与在线数据库不同。我基本上想用备份替换服务器上的数据库。调用 SqlRestore 时出现异常。

主要的例外说

{"服务器恢复失败 '本地主机'。 "}

深入了解内部异常会显示这些错误

执行时发生异常 Transact-SQL 语句或批处理。

然后

逻辑文件“DB”不属于 数据库“数据库”。使用恢复 FILELISTONLY 列出逻辑文件 名称。\r\nRESTORE DATABASE 是 异常终止。

我认为有一些方法可以告诉它只使用替换现有数据库。

我使用这段代码来获取数据库的文件路径,以便有一个目录来转储备份。也许这可以用来重新创建文件名。

public string GetDBFilePath(String databaseName, String userName, String password, String serverName)
{
    ServerConnection connection = new ServerConnection(serverName, userName, password);
    Server sqlServer = new Server(connection);
    Database db = sqlServer.Databases[databaseName];
    return sqlServer.Databases[databaseName].PrimaryFilePath;
}

【问题讨论】:

    标签: c# .net sql-server backup smo


    【解决方案1】:

    我将备份和恢复功能更改为如下所示:

    public void BackupDatabase(SqlConnectionStringBuilder csb, string destinationPath)
    {
        ServerConnection connection = new ServerConnection(csb.DataSource, csb.UserID, csb.Password);
        Server sqlServer = new Server(connection);
    
        Backup bkpDatabase = new Backup();
        bkpDatabase.Action = BackupActionType.Database;
        bkpDatabase.Database = csb.InitialCatalog;
        BackupDeviceItem bkpDevice = new BackupDeviceItem(destinationPath, DeviceType.File);
        bkpDatabase.Devices.Add(bkpDevice);
        bkpDatabase.SqlBackup(sqlServer);
        connection.Disconnect();
    
    }
    
    public void RestoreDatabase(String databaseName, String backUpFile, String serverName, String userName, String password)
    {
        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);
    }
    

    这样他们只使用那里的任何文件。不再有重新定位文件的指令。

    【讨论】:

    • 如果您从同一台机器上的同一数据库的备份中恢复,则无需重新定位文件。只有在通过备份/恢复移动和复制数据库时才需要重新定位。
    • 好的,这里有一些提示:关于备份文件路径,请始终注意该文件是否确实存在于您的源文件夹中。关于重定位,可能是写入 mdf 文件的权限问题。请注意您的应用是否有权读取 .bak 文件,在这种情况下请检查 SQL 配置管理器:MSSQLServer 服务必须在 LocalSystem 用户下运行。
    【解决方案2】:

    感谢莱姆斯的回答!

    我已经修改了

    sqlRestore.RelocateFiles.Add(new RelocateFile(databaseName, dataFileLocation));
    sqlRestore.RelocateFiles.Add(new RelocateFile(databaseName + "_log", logFileLocation)); 
    

    这两行

    System.Data.DataTable logicalRestoreFiles = sqlRestore.ReadFileList(sqlServer);
    sqlRestore.RelocateFiles.Add(new RelocateFile(logicalRestoreFiles.Rows[0][0].ToString(), dataFileLocation));
    sqlRestore.RelocateFiles.Add(new RelocateFile(logicalRestoreFiles.Rows[1][0].ToString(), logFileLocation));
    

    我的代码运行成功。

    感谢支持!

    【讨论】:

    • @Pallavi 您的解决方案立即为我工作。但我无法理解该解决方案,请您简要介绍您的解决方案答案。
    • 这个解决方案对我来说也很完美。对于那些想要更多的人来说,localRestoreFiles 拥有的是源数据库“文件列表”。该数据库的文件列表,例如创建的所有 MDF、日志和索引文件。但是,这些 Rows[X] 数字假设您有一个只有 1 个 MDF 和 1 个 LDF 的普通数据库(例如,没有额外的日志或索引文件)。如果是这种情况,Rows[0] 包含第一个 MDF 文件,Rows[1] 将是日志文件。并且 Rows[0][0] 和 Rows[1][0] 将包含您可以用来“移动”的逻辑数据库名称(区分大小写!)。
    【解决方案3】:

    您正在根据数据库名称添加RelocateFile 选项,这是不正确的。您应该根据重定位的每个文件的逻辑文件名添加它们。使用Restore.ReadFileList 检索逻辑文件名列表。

    【讨论】:

    • 看来我不能把这些选项加在一起。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-22
    • 2021-04-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多