【问题标题】:Best way to restore a database with FILESTREAM data using C# (SMO)使用 C# (SMO) 恢复包含 FILESTREAM 数据的数据库的最佳方法
【发布时间】:2020-03-27 21:48:16
【问题描述】:

我正在编写一个简单的 C# 应用程序,它允许用户通过选择数据库的路径并为数据库提供一个新名称来恢复数据库 - 我的问题是;

  1. 恢复功能仍在寻找生成备份的路径并失败
  2. 数据库备份包含 FILESTREAM 数据并且也失败了,因为我似乎也无法解释/或重新定位它。

代码 C#

    Restore dbRestore = new Restore();
    BackupDeviceItem deviceItem = new BackupDeviceItem(filePath, DeviceType.File);
    dbRestore.Devices.Add(deviceItem);
    dbRestore.Database = databaseName;

    ServerConnection connection = new ServerConnection(serverName, userName, password);
    Server sqlServer = new Server(connection);

    Database db = sqlServer.Databases[databaseName];
    dbRestore.Action = RestoreActionType.Database;
    String dataFileLocation = dataFilePath + databaseName + ".mdf";
    String logFileLocation = logFilePath + databaseName + "_Log.ldf";
    db = sqlServer.Databases[databaseName];
    DataTable dtFileList = dbRestore.ReadFileList(sqlServer);
    string dbLogicalName = dtFileList.Rows[0][0].ToString();
    string logLogicalName = dtFileList.Rows[1][0].ToString();
    dbRestore.RelocateFiles.Add(new RelocateFile(dbLogicalName, dataFileLocation));
    dbRestore.RelocateFiles.Add(new RelocateFile(logLogicalName + "_log", logFileLocation));
    dbRestore.ReplaceDatabase = true;

    dbRestore.dbRestore(sqlServer);
    db = sqlServer.Databases[databaseName];
    db.SetOnline();
    sqlServer.Refresh();
}
catch (Exception ex)
{
    Console.Write(ex.ToString());

    MessageBox.Show(ex.Message, "This is exception for testing");
}

##error

抛出异常: 'Microsoft.SqlServer.Management.Smo.FailedOperationException' 在 Microsoft.SqlServer.SmoExtended.dll Microsoft.SqlServer.Management.Smo.FailedOperationException:恢复 服务器“SERVERNAME”失败。 ---> Microsoft.SqlServer.Management.Common.ExecutionFailureException:一个 执行 Transact-SQL 语句或批处理时发生异常。 ---> System.Data.SqlClient.SqlException:逻辑文件“DatabaseDemo_4do6_EM_INDEXGROUP_log”不是数据库的一部分 '新数据库名称'。使用 RESTORE FILELISTONLY 列出逻辑文件 名字。 RESTORE DATABASE 异常终止。在 Microsoft.SqlServer.Management.Common.ConnectionManager.ExecuteTSql(ExecuteTSqlAction 动作、对象 execObject、数据集 fillDataSet、布尔值 catchException) 在 Microsoft.SqlServer.Management.Common.ServerConnection.ExecuteNonQuery(字符串 sqlCommand, ExecutionTypes executionType, Boolean retry) --- End of 内部异常堆栈跟踪 --- 在 Microsoft.SqlServer.Management.Common.ServerConnection.ExecuteNonQuery(字符串 sqlCommand, ExecutionTypes executionType, Boolean retry) at Microsoft.SqlServer.Management.Common.ServerConnection.ExecuteNonQuery(StringCollection sqlCommands, ExecutionTypes executionType, Boolean retry) at Microsoft.SqlServer.Management.Smo.BackupRestoreBase.ExecuteSql(服务器 服务器,StringCollection 查询)在 Microsoft.SqlServer.Management.Smo.Restore.SqlRestore(服务器 srv)
--- 内部异常堆栈跟踪结束 --- 在 Microsoft.SqlServer.Management.Smo.Restore.SqlRestore(Server srv) 程序“[14052] OPSAdmin.exe”已退出,代码为 -1 (0xffffffff)。

问题

  1. 我怎样才能有效地做到这一点,同时还要考虑文件流数据
  2. 我的“RelocateFiles”功能有什么问题。

谢谢。!!

【问题讨论】:

  • dtFileList 中是否还有更多行?
  • @DavidBrowne-Microsoft - 好的,是的,dtFileList 中有更多行,当我重新定位它们时,恢复工作正常,但我的问题是如何动态处理这个问题,考虑到某些数据库可能有更多dtFileList 中的行数多于其他行?感谢您的意见。

标签: c# .net sql-server winforms


【解决方案1】:

您需要定义单独的变量来保存 Filestream 文件组名称。

String fileStreamFGPhysicalPath = dataFilePath + databaseName;
string fileStreamFGLogicalName;
string dbLogicalName;
string logLogicalName;

您需要遍历数据表来识别文件流逻辑名称。您可以使用 FileType 列来识别它。

 DataTable dtFileList = dbRestore.ReadFileList(sqlServer);

 Foreach(DataRow dr in dtFileList)
{
   switch (dr["Type"])
    {     
     case "D":
      dbLogicalName = dr["LogicalName"].ToString();
      break;
     case "L":
      logLogicalName = dr["LogicalName"].ToString();
      break;
     case "S":
      fileStreamFGLogicalName= dr["LogicalName"].ToString();
      break;
    }
}

现在,也为文件流定义重定位文件。

dbRestore.RelocateFiles.Add(new RelocateFile(dbLogicalName, dataFileLocation));
dbRestore.RelocateFiles.Add(new RelocateFile(logLogicalName + "_log", logFileLocation));
dbRestore.RelocateFiles.Add(new RelocateFile(fileStreamFGLogicalName , fileStreamFGPhysicalPath ));

注意:我在这里只考虑了三个文件:数据、日志、文件流。您可能有多个数据文件。因此,您需要将数据文件名称作为数组并在 Relocatefiles 中相应地移动它们。

【讨论】:

  • 感谢@venkataraman 的输入,这很有效。关于你的回复,我确实有一个后续问题。我如何动态处理这个?我按照建议更新了我的代码,它适用于 DataTable 中只有 3 个条目的数据库,但是当我尝试使用 4 个条目的不同数据库时,它失败了。当不同数据库的 DataTable 中的条目不同时,您如何建议我动态处理此问题?提前致谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-21
  • 2012-01-01
相关资源
最近更新 更多