无法将.bak文件还原到数据库

时间:2016-01-03 15:31:06

标签: c#

我已使用smo restore方法成功恢复了数据库。但是当我尝试将相同的.bak文件恢复到另一个数据库时,它会返回一个异常,如下所示

enter image description here

我从我使用的.bak数据库模板创建了GC_BranchName文件。 GC_Muntinlupa是我创建的第一个数据库,并成功恢复了.bak文件。有人可以就此提出建议吗?

这是我的恢复代码:

bool RestoreDB(string name)
    {

        try
        {
            var connection = new ServerConnection(Properties.Settings.Default.Well);
            var sqlServer = new Server(connection);
            var rstDatabase = new Restore();

            rstDatabase.Database = name;
            rstDatabase.Action = RestoreActionType.Database;
            rstDatabase.Devices.AddDevice(System.Environment.CurrentDirectory + "\\GC.bak", DeviceType.File);
            rstDatabase.ReplaceDatabase = true;
            rstDatabase.SqlRestore(sqlServer);

            connection.Disconnect();
            return true;
        }
        catch (Exception ex)
        {
            MessageBox.Show("A problem occured when building the branch!" + ex, "Monytron Consolidator", MessageBoxButtons.OK, MessageBoxIcon.Error);
            return false; 
        }

2 个答案:

答案 0 :(得分:0)

对不起J.P Masangcay,但到目前为止我还没来得及为你们所有人。 以下是适合您的解决方案,由我验证。

您的问题是,如果将数据库备份还原到新数据库,则会出现文件错误。

为什么文件冲突?

SQL Server的默认行为是使用文件路径和数据和日志文件的名称来恢复数据库,就像备份时一样。因此,如果在还原过程中存在该原始数据库,则会导致文件系统冲突。如果将数据库备份模板多次还原到另一台服务器,则会出现相同的冲突。

你的案子:

数据库:GC_BranchName

数据文件:GC_BranchName.mdf

日志文件:GC_BranchName_log.ldf

Resore数据库:GC_Muntinlupa

数据文件: GC_BranchName.mdf

日志文件: GC_BranchName_log.ldf

要解决问题,您必须重新定位文件以使数据库具有不同的文件名。这是一个解决方案,它简单地添加/预先设置了新的数据库名称"到所有文件。这种重新定位在引擎盖下使用TSQL恢复数据库" RESTORE DATABASE ... WITH MOVE"选项,如上面的例外情况所示。

Resore数据库:GC_Muntinlupa

数据文件: GC_Muntinlupa_GC_BranchName.mdf

日志文件: GC_Muntinlupa_GC_BranchName_log.ldf

bool RestoreDB(string name)
{
    try
    {
        var connection = ServerConnection(Properties.Settings.Default.Well);
        var sqlServer = new Server(connection);
        var rstDatabase = new Restore();

        rstDatabase.Database = name;
        rstDatabase.Action = RestoreActionType.Database;
        rstDatabase.Devices.AddDevice(System.Environment.CurrentDirectory + "\\GC.bak", DeviceType.File);
        rstDatabase.ReplaceDatabase = true;

        foreach (DataRow r in rstDatabase.ReadFileList(sqlServer).Rows)
        {
            var relocateFile = new RelocateFile();

            relocateFile.LogicalFileName = r["LogicalName"].ToString();

            // move/rename physical filename by prepending database name to prevent FileSystem conflicts
            var physicalName = r["PhysicalName"].ToString();
            var path = System.IO.Path.GetDirectoryName(physicalName);
            var filename = System.IO.Path.GetFileName(physicalName);
            physicalName = System.IO.Path.Combine(path, string.Format("{0}_{1}", name, filename));

            relocateFile.PhysicalFileName = physicalName;

            rstDatabase.RelocateFiles.Add(relocateFile);
        }

        rstDatabase.SqlRestore(sqlServer);

        connection.Disconnect();
        return true;
    }
    catch (Exception ex)
    {
        MessageBox.Show("A problem occured when building the branch!" + ex, "Monytron Consolidator", MessageBoxButtons.OK, MessageBoxIcon.Error);
        return false;
    }
}

答案 1 :(得分:0)

这应该可以解决问题

namespace DB_Restore
{
    class Program
    {
        static void Main(string[] args)
        {
            RestoreDatabase();
        }
        public static void RestoreDatabase()
        {
            try
            {
                ServerConnection connection = new ServerConnection(@"Server\instance", "uname", "PWD");
                Server sqlServer = new Server(connection);
                Restore rstDatabase = new Restore();
                rstDatabase.Action = RestoreActionType.Database;
                rstDatabase.Database = "H5MI_Automation_Restore_Backup";
                BackupDeviceItem bkpDevice = new BackupDeviceItem(@"E:\DATA\QA_SP\MSSQL11.QA_SP\MSSQL\Backup\H5MI_Automation.bak", DeviceType.File);
                rstDatabase.Devices.Add(bkpDevice);
                rstDatabase.ReplaceDatabase = true;
                //As mentioned in the above solution this code will take care .mdf and .ldf file location issue
                foreach (DataRow r in rstDatabase.ReadFileList(sqlServer).Rows)
                {
                    var relocateFile = new RelocateFile();
                    relocateFile.LogicalFileName = r["LogicalName"].ToString();
                    Console.WriteLine(relocateFile.LogicalFileName);
                    var physicalName = r["PhysicalName"].ToString();
                    Console.WriteLine(physicalName);
                    var path = System.IO.Path.GetDirectoryName(physicalName);
                    Console.WriteLine(path);
                    var filename = System.IO.Path.GetFileName(physicalName);
                    Console.WriteLine(filename);
                    physicalName = path + @"\H5MI_Automation_Restore_Backup_" + filename;
                    Console.WriteLine(physicalName);
                    relocateFile.PhysicalFileName = physicalName;
                    Console.WriteLine(relocateFile.PhysicalFileName);
                    Console.WriteLine(relocateFile);
                    rstDatabase.RelocateFiles.Add(relocateFile);
                }
                rstDatabase.SqlRestore(sqlServer);
                connection.Disconnect();
            }
            catch (Exception e)
            {

                Console.Write(e);
            }
        }
    }
}

添加代码说明。实质上,上述屏幕快照中的问题是由于.mdf和.ldf文件位置所致。当您尝试手动还原数据库时,u也会遇到相同的问题。附加屏幕截图。Manual DB restore

为什么会抛出错误? 这是因为该文件由实际的DB使用(从中生成.bak文件)

因此,这段代码将帮助您更改.mdf和.ldf文件路径的位置。

 foreach (DataRow r in rstDatabase.ReadFileList(sqlServer).Rows)
                {
                    var relocateFile = new RelocateFile();
                    relocateFile.LogicalFileName = r["LogicalName"].ToString();
                    Console.WriteLine(relocateFile.LogicalFileName);
                    var physicalName = r["PhysicalName"].ToString();
                    Console.WriteLine(physicalName);
                    var path = System.IO.Path.GetDirectoryName(physicalName);
                    Console.WriteLine(path);
                    var filename = System.IO.Path.GetFileName(physicalName);
                    Console.WriteLine(filename);
                    physicalName = path + @"\H5MI_Automation_Restore_Backup_" + filename;
                    Console.WriteLine(physicalName);
                    relocateFile.PhysicalFileName = physicalName;
                    Console.WriteLine(relocateFile.PhysicalFileName);
                    Console.WriteLine(relocateFile);
                    rstDatabase.RelocateFiles.Add(relocateFile);
                }