如何从 C# 恢复数据库

发布于 2024-08-05 19:09:43 字数 2145 浏览 1 评论 0 原文

我有一个 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”不属于 数据库“DB”。使用恢复 FILELISTONLY 列出逻辑文件 名称。\r\n恢复数据库是 异常终止。

我假设有某种方法可以告诉它仅按原样替换现有数据库。

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

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

I have a SQL 2008 DB. I am running a form that backs that DB up, then tries to update it. If the update fails the idea is to restore that backup. Here is the code I am using to restore the backup.

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

The issue seems to be that the file names I pick are different from the online DB. I basically want to replace the database on the server with the backup. I get an exception when I call SqlRestore.

The main exception says

{"Restore failed for Server
'localhost'. "}

Digging into the inner exceptions shows these errors

An exception occurred while executing
a Transact-SQL statement or batch.

and then

Logical file 'DB' is not part of
database 'DB'. Use RESTORE
FILELISTONLY to list the logical file
names.\r\nRESTORE DATABASE is
terminating abnormally.

I assume there is some way to tell this to just use replace the existing DB as is.

I use this bit of code to get the file path of the DB to have a directory to dump the backup. Maybe this could be used to get the file names to recreate.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

深海蓝天 2024-08-12 19:09:43

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

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

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

I changed my back up and restore functions to look like this:

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

That way they just use whatever files are there. There are no longer and directives to relocate files.

拍不死你 2024-08-12 19:09:43

感谢莱姆斯的回答!

我已将

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

并且我的代码运行成功。

感谢您的支持!

Thanks Remus for your answer!

I have modified

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

these two lines to

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

and my code is running successfully.

Thanks for the support!

嘿看小鸭子会跑 2024-08-12 19:09:43

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

You are adding RelocateFile options based on the database name, that is incorrect. You should add them based on the logical file name for each file relocated. Use Restore.ReadFileList to retrieve the list of logical file names.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文