В Delphi есть способ резервного копирования и восстановления базы данных с помощью FireDAC

Есть ли способ резервного копирования и восстановления базы данных с помощью FireDAC?

Я использую Delphi 10.1 Berlin и подключаюсь к MSSQL Server. В идеале было бы создать резервную копию всех интересных атрибутов базы данных (записи, индексы и т. д.), но решение, которое просто выполняет резервное копирование и восстановление данных, было бы хорошо (я могу воссоздать все метаданные перед восстановлением).


person Alister    schedule 28.03.2017    source источник
comment
Разве это не задача администрирования базы данных, решаемая на уровне ИТ? Почему это должно быть сделано в Delphi? Бэкапы обычно делаются на самом сервере. Перекачка всех данных клиенту БД будет потреблять много ресурсов, практически без пользы. Если вы ожидаете чего-то более легкого, переключитесь на альтернативы, например. SQLite3 с клиент-серверным уровнем REST: создавать резервные копии таких баз данных легко — вам просто нужно скопировать файл или использовать API резервного копирования.   -  person Arnaud Bouchez    schedule 28.03.2017
comment
@ArnaudBouchez, один из моих клиентов распространяет MSSQL Express с каждой поставленной машиной. В то время как другие клиенты обращаются к этому серверу с разных машин, в той же системе, что и SQL Server, работает главное/серверное приложение. Было бы неплохо реализовать механизмы резервного копирования и восстановления прямо внутри этого приложения. В настоящее время мы решаем эту проблему, выполняя внешние приложения с меньшим контролем над процессом. Кстати, переход на другую базу данных здесь невозможен.   -  person Uwe Raabe    schedule 28.03.2017
comment
@ArnaudBouchez Это настольное программное обеспечение, у большинства пользователей сервер (экспресс) работает на их компьютере (установка для одного пользователя или небольшая сеть), в то время как другие подключатся к соответствующему серверу (корпоративная установка).   -  person Alister    schedule 29.03.2017


Ответы (1)


Признаюсь, я немного озадачен вашим вопросом, потому что ответ кажется слишком простым, а именно использовать FireDAC TDFConnection для выполнения сценариев SqlServer TransactSql для резервного копирования и восстановления базы данных. Надеюсь, вы не считаете это читерством ;)

Пример кода проекта

type
  TForm1 = class(TForm)
    FDConnection1: TFDConnection;
    btnBackUp: TButton;
    btnRestore: TButton;
    FDMetaInfoQuery1: TFDMetaInfoQuery;
    FDPhysMSSQLDriverLink1: TFDPhysMSSQLDriverLink;
    DBGrid1: TDBGrid;  //  connected to DataSource1
    DataSource1: TDataSource;  // connected to FDMetaInfoQuery1
    Memo1: TMemo;
    procedure btnBackUpClick(Sender: TObject);
    procedure btnRestoreClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  [...]

const
  scBackUpPath = 'D:\MSSql2014\Backup\';
  scBackupExtn = '.Bak';

procedure TForm1.Log(const Msg : String);
begin
  Memo1.Lines.Add(Msg);
end;

function TForm1.DatabaseName: String;
begin
  Result := FDMetaInfoQuery1.FieldByName('Catalog_Name').AsString;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FDMetaInfoQuery1.MetaInfoKind := mkCatalogs;  // gets list of databases
  FDConnection1.Connected := True;
end;

procedure TForm1.BackupDB(const DBName: String);
var
  FileName,
  Sql : String;
begin
  FileName := scBackUpPath + DBName + scBackUpExtn;
  Sql := 'backup database %s to disk = ''%s''';
  Sql := Format(Sql, [DBName, FileName]);
  Log('Backing up ' + DBName + ' using SQL: ' + Sql);
  try
    Screen.Cursor := crHourGlass;
    Update;
    FDConnection1.ExecSQL(Sql);
    Log('Done');
  finally
    Screen.Cursor := crDefault;
  end;
end;

procedure TForm1.btnBackUpClick(Sender: TObject);
begin
  BackUpDB(DatabaseName);
end;

procedure TForm1.btnRestoreClick(Sender: TObject);
begin
  RestoreDB(DatabaseName);
end;

procedure TForm1.RestoreDB(const DBName: String);
var
  FileName,
  Sql : String;
begin
  FileName := scBackUpPath + DBName + scBackUpExtn;
  if FileExists(FileName) then begin
    //  Note:  beware the 'with replace' in the following
    Sql := 'restore database %s from disk = ''%s'' with replace';
    Sql := Format(Sql, [DBName, FileName]);
    Log('Restoring ' + DBName + ' using SQL: ' + Sql);
    try
      Screen.Cursor := crHourGlass;
      Update;
      FDConnection1.ExecSQL(Sql);
      Log('Done');
    finally
      Screen.Cursor := crDefault;
    end;
  end
  else
    Log('Backup file ' + FileName + ' not found!');
end;

Очевидно, что это немного упрощает проверку ошибок, но я уверен, что вы поймете эту идею.

До того, как это было прекращено, я использовал автоматизацию Delphi для библиотеки SqlServer Sql-DMO, чтобы сделать это, потому что было легко реализовать обратные вызовы прогресса, такие как «% завершено».

Мне еще не удалось сделать ничего полезного с преемником Sql_DOM, SMO, от Delphi, и в эти дни я бы сделал это, используя TADOConnection, а не FireDAC, хотя бы потому, что при получении списка баз данных и коллекции ошибок ADO меньше багажа. обеспечивает простой способ получения любых обнаруженных ошибок.

person MartynA    schedule 28.03.2017
comment
Кажется, это работает хорошо. Я, вероятно, смогу жить без прогресса, поскольку базы данных относительно малы (менее 100 МБ), поэтому необходимо быстро выполнять резервное копирование и восстановление. - person Alister; 29.03.2017
comment
Мне удалось сделать что-то полезное с преемником Sql_DOM, SMO, из Delphi, SMO предназначен только для .NET, поэтому вам придется написать для него оболочку. Хотя совет хороший! - person Victoria; 06.06.2017
comment
@Виктория. Спасибо, я знал о необходимости оболочки для SMO, поэтому не стал ничего с этим делать. Единственной причиной, по которой я раньше использовал DMO, была простота, с которой можно получить обратные вызовы прогресса для длительных операций, и мне не хотелось прыгать через обручи, чтобы заставить SMO работать только для того, чтобы найти с ними какую-то проблему остановки шоу. - person MartynA; 06.06.2017