[.NET, C#, Разработка под Windows] Делаем откаты БД в msi. История про создание резервных копий и удаление БД в WixSharp
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
При работе с базами данных (БД) в установщике, про который мы уже писали в прошлой статье (Пишем установщик на WixSharp. Плюшки, проблемы, возможности), в первую очередь, были реализованы проверка доступности СУБД по логину/паролю, добавление и обновление собственно БД (в нашем приложении их несколько) накатыванием миграций, a также добавление пользователей. Все это реализовано для двух СУБД Microsoft SqlServer и PostgreSql.
На первый взгляд этого достаточно, но иногда есть необходимость удалять БД и пользователей, а это влечет за собой создание резервных копий. Сразу выявили две необходимые задачи:1. Удаление БД и пользователей при откате приложения в случае ошибки при первичной установке. При установке приложения, если возникает ошибка, происходил откат всех настроек, кроме БД. Добавленные БД и пользователи оставались. И, если при боевой эксплуатации, после серии тестирования эта ситуация непредвиденной ошибки маловероятна, то в процессе разработки и доработки установщика, ошибки возникают часто. Их, однозначно, нужно удалять.2. Создание резервных копий (бэкапов) и удаление БД и пользователей при полном удалении приложения установщиком. Правильно ли оставлять БД после полного удаления приложения? Мы решили, что нет. Но бэкапы, конечно, сохранять нужно. Из второго пункта возникла новая задача:3. Создание бэкапов БД при обновлении приложения. Если мы сохраняем бэкапы при удалении, неплохо создавать их и перед обновлением, накатыванием миграций и прочими изменениями. Подстраховка еще никому не мешала. :)
Удаление БД и пользователей при откате приложения в случае ошибки при первичной установкеЕсли что-то пошло не так и при установке возникли ошибки, мы сразу же позаботились об удалении добавленных директорий и настроек, а также об очистке реестра. Но БД и пользователей также нужно удалять. В WixSharp для этого предусмотрен механизм роллбэка для CustomActions. Для существующего пользовательского действия нужно добавить еще один параметр - название пользовательского действия откатывающего изменения. Необходимо учесть, что данный механизм доступен только для deferred action (отложенных действий).
new ManagedAction(AddDatabaseAction, Return.check, When.After, Step.PreviousAction, Condition.NOT_Installed, DeleteAddedDatabasesAction)
{
UsesProperties = $@"{DATABASE_PROPERTIES}={database_properties}",
Execute = Execute.deferred,
ProgressText = $"Выполняется создание БД {databaseName}"
};
Тут сложностей не возникло и для каждого из СУБД было добавлено выполнение скрипта с удалением БД и пользователей, учитывая в скрипте, что в этот момент база может использоваться. Создание бэкапов и удаление БД при полном удалении приложения установщикомВ данном случае, необходимо сохранять бэкапы БД, а затем, проводить удаление. Пользовательское действие для создания бэкапа желательно выполнять до того, как начнут вноситься изменения установщиком, для этого предусмотрен тип immediate. В отличие от deferred, он выполняется сразу. Чтобы данное действие выполнялось только при удалении приложения, укажем условие Condition.BeingUninstalled:
new ManagedAction(BackupDatabaseAction, Return.check, When.After, Step.PreviousAction, Condition.BeingUninstalled)
{
Execute = Execute.immediate,
UsesProperties = DeleteAddedDatabases,
ProgressText = $"Выполняется скрипт по созданию резервных копий БД"
}
Бэкапы решено было сохранять по пути, доступному текущему пользователю. Так как у нас несколько БД, группировку проводили по версии приложения. Название БД формировалось классически, с указанием имени и даты-времени создания.
\Users\{CurrentUser}\AppData\Local\{ApplicationName}\Backups\{VersionNumber}Создаем этот путь:
Version installedVersion = session.LookupInstalledVersion();
string localUserPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
string backupPath = Path.Combine(localUserPath, "ApplicationName", "Backups", installedVersion.ToString());
Directory.CreateDirectory(backupPath);
И если для Microsoft SqlServer создание бэкапов заключалось в выполнении банального sql-скрипта:
$" USE master" +
$" BACKUP DATABASE [{databaseName}]" +
$" TO DISK = N'{path}'" +
$" WITH NOFORMAT, NOINIT, " +
$" NAME = N'{backupName}', SKIP, NOREWIND, NOUNLOAD, STATS = 10 ";
То для PostgreSql одним скриптом не обойтись. Бэкап можно создать запуском команды через командную строку. Понадобится выполнение следующих действий:
- Запускать pg_dump.exe из соответствующей папки PostgreSql
C:\Program Files\PostgreSQL\{Version}\bin
Мы не знаем какая версия установлена у заказчика (обычно в документации мы указываем версию, не ниже которой требуется), какой путь был выбран. Поэтому основной путь с указанием версии получим из реестра:
const string KEY_MASK = @"SOFTWARE\PostgreSQL\Installations";
var currentVersion = Registry.LocalMachine.OpenSubKey(KEY_MASK)?.GetSubKeyNames()[0];
if (currentVersion == null)
{
return ActionResult.Failure;
}
var keyName = $@"HKEY_LOCAL_MACHINE\{KEY_MASK}{currentVersion}";
var postgresPath = (string)Registry.GetValue(keyName, "Base Directory", string.Empty);
- Проверять, добавлены ли переменные среды для PostgreSql. И в случае необходимости добавить.
C:\Program Files\PostgreSQL\12\bin
C:\Program Files\PostgreSQL\12\lib
Если они отсутствуют, запуск pg_dump будет невозможен.
string binEnv = $@"{postgresPath}\bin";
string path = "PATH";
var scope = EnvironmentVariableTarget.User;
var currentEnvironmentVariable = Environment.GetEnvironmentVariable(name, scope);
if (!currentEnvironmentVariable.ToUpper().Contains(binEnv.ToUpper()))
{
var newEnvironmentVariable = $@"{currentEnvironmentVariable};{binEnv}";
Environment.SetEnvironmentVariable(name, newEnvironmentVariable, scope);
}
- Сформировать аргументы создания бэкапа с помощью командной строки. Здесь необходимо указать параметры подключения, имя БД и путь сохранения бэкапа. Так как ранее нам не приходилось создавать бэкапы для PostgreSql, несложный поиск в интернете показывал примерно такое решение:
pg_dump -h {host} -p {port} -U {username} {database_name} > {backuppath}
Если в конфиг файле pg_hba не указано для local connections безусловное подключение trust, то будет требоваться введение пароля. В данном случае, требуется добавление файла .pgpass для текущего пользователя. Тогда, можно добавить в команду атрибут -w и пароль будет считываться оттуда. Так как вновь возникает ситуация, когда мы не знаем, как это организовано у заказчика, была найдена универсальная запись, с помощью которой можно передать все параметры в рамках одной команды:
pg_dump --dbname=postgresql://{username}:{password}@{address}:{port}
/{databaseName} -f {backupPath}
После того, как бэкапы созданы, можно удалить БД и пользователей. Здесь будет использоваться то же пользовательское действие DeleteAddedDatabasesAction, что и для отката из пункта 1. Оно будет отложенным и будет запускаться при условии деинсталляции Condition.BeingUninstalled:
new ManagedAction(DeleteAddedDatabasesAction, Return.check, When.After, Step.PreviousAction, Condition.BeingUninstalled)
{
Execute = Execute.deferred,
UsesProperties = $@"{DATABASE_PROPERTIES}={database_properties}",
ProgressText = $"Выполняется удаление БД {databaseName} и роли {role}"
};
Операции с БД при обновлении приложенияПри обновлении приложения последовательно происходит удаление, инициализация данных из реестра и установка новой версии. До внесения наших изменений все было хорошо, базы и пользователи оставались жить. Теперь нужно отличать чистое удаление от удаления при обновлении. Решили мы это добавлением новой переменной в реестр, которая инициализируется при обновлении (определяем сравнением версий), а также фиксацией пользовательского действия удаления.ВыводДля PostgreSql и Microsoft SqlServer в нашем установщике удалось наладить:
- механизм удаления БД и пользователей;
- создание резервных копий в случае полного удаления;
- создание резервных копий в случае обновления приложения;
- реализацию отката добавленных БД в случае неудачной первичной установки, либо ее отмене. Продолжаем пилить msi ;)
===========
Источник:
habr.com
===========
Похожие новости:
- [Исследования и прогнозы в IT, Разработка под Windows, Софт] Какие изменения ждут разработчиков после выхода новой Windows 10X (перевод)
- [Open source, .NET, XML, C#] Конвертируем ODT в XML
- [.NET, C#] Разделённые запросы в EF Core
- [PostgreSQL, Java, Тестирование веб-сервисов] История о PostgreSQL 13, Testcontainers и багах
- [.NET, C#] Shrinking .NET Console Application (перевод)
- [Интерфейсы, Разработка под Windows, Дизайн, Софт] В Windows 10 21H2 появится новый параметр в меню питания, изоляция сторонних драйверов и процесс taskbar.dll (перевод)
- [Open source, .NET, C#] Избавляемся от постоянного написания конструкторов для инжекта зависимостей с помощью C# Source Generators
- [PostgreSQL] Рекомендации по развертыванию Гибридного Облака (Hybrid Cloud) PostgreSQL (перевод)
- [Браузеры, Разработка под Windows, Софт] Windows 10 при установке с диска иногда не устанавливает Edge
- [.NET, C#, Программирование микроконтроллеров, Интернет вещей, DIY или Сделай сам] .NET nanoFramework — платформа для разработки приложений на C# для микроконтроллеров
Теги для поиска: #_.net, #_c#, #_razrabotka_pod_windows (Разработка под Windows), #_backup, #_postgresql, #_mssql, #_rollback, #_wix#, #_wixsharp, #_msi, #_blog_kompanii_cross_technologies (
Блог компании Cross Technologies
), #_.net, #_c#, #_razrabotka_pod_windows (
Разработка под Windows
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 08:34
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
При работе с базами данных (БД) в установщике, про который мы уже писали в прошлой статье (Пишем установщик на WixSharp. Плюшки, проблемы, возможности), в первую очередь, были реализованы проверка доступности СУБД по логину/паролю, добавление и обновление собственно БД (в нашем приложении их несколько) накатыванием миграций, a также добавление пользователей. Все это реализовано для двух СУБД Microsoft SqlServer и PostgreSql. На первый взгляд этого достаточно, но иногда есть необходимость удалять БД и пользователей, а это влечет за собой создание резервных копий. Сразу выявили две необходимые задачи:1. Удаление БД и пользователей при откате приложения в случае ошибки при первичной установке. При установке приложения, если возникает ошибка, происходил откат всех настроек, кроме БД. Добавленные БД и пользователи оставались. И, если при боевой эксплуатации, после серии тестирования эта ситуация непредвиденной ошибки маловероятна, то в процессе разработки и доработки установщика, ошибки возникают часто. Их, однозначно, нужно удалять.2. Создание резервных копий (бэкапов) и удаление БД и пользователей при полном удалении приложения установщиком. Правильно ли оставлять БД после полного удаления приложения? Мы решили, что нет. Но бэкапы, конечно, сохранять нужно. Из второго пункта возникла новая задача:3. Создание бэкапов БД при обновлении приложения. Если мы сохраняем бэкапы при удалении, неплохо создавать их и перед обновлением, накатыванием миграций и прочими изменениями. Подстраховка еще никому не мешала. :) Удаление БД и пользователей при откате приложения в случае ошибки при первичной установкеЕсли что-то пошло не так и при установке возникли ошибки, мы сразу же позаботились об удалении добавленных директорий и настроек, а также об очистке реестра. Но БД и пользователей также нужно удалять. В WixSharp для этого предусмотрен механизм роллбэка для CustomActions. Для существующего пользовательского действия нужно добавить еще один параметр - название пользовательского действия откатывающего изменения. Необходимо учесть, что данный механизм доступен только для deferred action (отложенных действий). new ManagedAction(AddDatabaseAction, Return.check, When.After, Step.PreviousAction, Condition.NOT_Installed, DeleteAddedDatabasesAction)
{ UsesProperties = $@"{DATABASE_PROPERTIES}={database_properties}", Execute = Execute.deferred, ProgressText = $"Выполняется создание БД {databaseName}" }; new ManagedAction(BackupDatabaseAction, Return.check, When.After, Step.PreviousAction, Condition.BeingUninstalled)
{ Execute = Execute.immediate, UsesProperties = DeleteAddedDatabases, ProgressText = $"Выполняется скрипт по созданию резервных копий БД" } \Users\{CurrentUser}\AppData\Local\{ApplicationName}\Backups\{VersionNumber}Создаем этот путь: Version installedVersion = session.LookupInstalledVersion();
string localUserPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); string backupPath = Path.Combine(localUserPath, "ApplicationName", "Backups", installedVersion.ToString()); Directory.CreateDirectory(backupPath); И если для Microsoft SqlServer создание бэкапов заключалось в выполнении банального sql-скрипта: $" USE master" +
$" BACKUP DATABASE [{databaseName}]" + $" TO DISK = N'{path}'" + $" WITH NOFORMAT, NOINIT, " + $" NAME = N'{backupName}', SKIP, NOREWIND, NOUNLOAD, STATS = 10 ";
const string KEY_MASK = @"SOFTWARE\PostgreSQL\Installations";
var currentVersion = Registry.LocalMachine.OpenSubKey(KEY_MASK)?.GetSubKeyNames()[0]; if (currentVersion == null) { return ActionResult.Failure; } var keyName = $@"HKEY_LOCAL_MACHINE\{KEY_MASK}{currentVersion}"; var postgresPath = (string)Registry.GetValue(keyName, "Base Directory", string.Empty);
string binEnv = $@"{postgresPath}\bin";
string path = "PATH"; var scope = EnvironmentVariableTarget.User; var currentEnvironmentVariable = Environment.GetEnvironmentVariable(name, scope); if (!currentEnvironmentVariable.ToUpper().Contains(binEnv.ToUpper())) { var newEnvironmentVariable = $@"{currentEnvironmentVariable};{binEnv}"; Environment.SetEnvironmentVariable(name, newEnvironmentVariable, scope); }
new ManagedAction(DeleteAddedDatabasesAction, Return.check, When.After, Step.PreviousAction, Condition.BeingUninstalled)
{ Execute = Execute.deferred, UsesProperties = $@"{DATABASE_PROPERTIES}={database_properties}", ProgressText = $"Выполняется удаление БД {databaseName} и роли {role}" };
=========== Источник: habr.com =========== Похожие новости:
Блог компании Cross Technologies ), #_.net, #_c#, #_razrabotka_pod_windows ( Разработка под Windows ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 08:34
Часовой пояс: UTC + 5