Лучший способ восстановить базу данных с данными FILESTREAM, используя C# (SMO) - PullRequest
1 голос
/ 28 марта 2020

Я пишу простое 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");
}

Ошибка ##

Исключение: «Microsoft.SqlServer. Management.Smo.FailedOperationException 'в Microsoft.SqlServer.SmoExtended.dll Microsoft.SqlServer.Management.Smo.FailedOperationException: восстановление не удалось для сервера' ИМЯ-СЕРВЕРА '. ---> Microsoft.SqlServer.Management.Common.ExecutionFailureException: исключение произошло при выполнении оператора или пакета Transact- SQL. ---> System.Data.SqlClient.SqlException: логический файл 'DatabaseDemo_4do6_EM_INDEXGROUP_log' не является частью базы данных 'NewDatabaseName'. Используйте RESTORE FILELISTONLY, чтобы перечислить логические имена файлов. ВОССТАНОВЛЕНИЕ БАЗЫ ДАННЫХ завершается ненормально. в Microsoft.SqlServer.Management.Common.ConnectionManager.ExecuteT Sql (действие ExecuteTSqlAction, объект execObject, DataSet fillDataSet, Boolean catchException) в Microsoft.SqlServer.Management.Common.ServerConnection.ExeryTewnTecance, sql2 --- Конец внутренней трассировки стека исключений --- в Microsoft.SqlServer.Management.Common.ServerConnection.ExecuteNonQuery (Строка sqlCommand, ExecutionTypes executeType, логическая повторная попытка) в Microsoft.SqlServer.Management.Common.ServerConnection.ExeryteCom ExecutionTypes executeType, Boolean retry) в Microsoft.SqlServer.Management.Smo.BackupRestoreBase.Execute Sql (сервер, запросы StringCollection) в Microsoft.SqlServer.Management.Smo.Restore.SqlRestore (Server srv) * 1019 --- Конец трассировки стека внутренних исключений --- в Microsoft.SqlServer.Management.Smo.Restore.SqlRestore (Server srv) Программа '[14052] OPSAdmin.exe' завершила работу с кодом -1 (0xffffffff) ).

Вопрос :

  1. Как я могу сделать это эффективно, а также учет данных файлового потока
  2. Каковы мои что-то не так с моей функцией RelocateFiles.

Спасибо. !!

1 Ответ

0 голосов
/ 15 апреля 2020

Вам необходимо определить отдельную переменную для хранения имени файловой группы Filestream.

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

Вам необходимо провести l oop через таблицу данных для определения логического имени файлового потока. Вы можете идентифицировать это, используя колонку 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...