2009-09-23 77 views
14

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

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

这个问题似乎是,文件名我选是从在线DB不同。我基本上想用备份替换服务器上的数据库。我调用SqlRestore时遇到异常。

主要的例外说

{ “恢复失败的服务器 'localhost' 的。”}

挖掘到内部异常显示这些错误

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

然后

逻辑文件 'DB' 是不是 数据库 'DB' 的一部分。使用RESTORE 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; 
} 

回答

18

我改变了我的备份和恢复功能,看起来像这样:

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

这样,他们只是使用任何文件都在那里。不再有和重定位文件的指示。

+3

如果您从同一机器上的相同数据库的备份进行恢复,则不需要重定位文件。只有在通过备份/恢复移动和复制数据库时才需要重新定位。 – 2009-09-23 16:28:13

+3

好的,这里有一些提示:关于备份文件路径,请务必注意,如果文件真的存在于源文件夹中。关于重定位,可能是写入mdf文件的权限问题。请注意,如果您的应用程序有权读取.bak文件,则在此情况下请检查SQL配置管理器:MSSQLServer服务必须在LocalSystem用户下运行。 – 2010-03-29 17:59:29

4

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

+0

看来我可以不添加这些选项一起。 – 2009-09-23 15:30:21

12

感谢Remus的回答!

我已经修改

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

和我的代码运行成功。

感谢您的支持!

+0

@Pallavi您的解决方案对我来说是直接工作的。但是我无法理解解决方案,请您简单介绍一下您的解决方案。 – 2013-08-08 14:17:45

+1

这个解决方案对我来说也是完美的。对于那些想要更多的人来说,localRestoreFiles保存的是源数据库“文件列表”。该数据库的文件列表,如创建的所有MDF,日志和索引文件。但是,这些行[X]数字假定您有一个只有1个MDF和1个LDF的普通数据库(例如没有附加日志或索引文件)。如果是这样的话,Rows [0]包含第一个MDF文件,Rows [1]将是日志文件。并且行[0] [0]和行[1] [0]将包含可用于“移动”的逻辑数据库名称(大小写敏感!)。 – eduncan911 2013-08-15 14:36:20