From 5cef1dcb4cad82e43bf3b8a47693a2ca1b07acdb Mon Sep 17 00:00:00 2001 From: Sergey Nazarov Date: Sat, 30 Mar 2024 11:48:50 +0300 Subject: [PATCH] Add persistence --- Directory.Packages.props | 2 + Nocr.Users.sln | 6 +++ src/Nocr.Users.Migrator/AddMigration.sh | 2 + .../DesignTimeTextMatcherContextFactory.cs | 37 +++++++++++++++++++ src/Nocr.Users.Migrator/Dockerfile | 19 ++++++++++ ...240330083951_InitialMigration.Designer.cs} | 4 +- .../20240330083951_InitialMigration.cs} | 2 +- .../Migrations/UsersContextModelSnapshot.cs | 2 +- .../Nocr.Users.Migrator.csproj | 37 +++++++++++++++++++ src/Nocr.Users.Migrator/Program.cs | 22 +++++++++++ src/Nocr.Users.Migrator/Readme.md | 10 +++++ src/Nocr.Users.Migrator/appsettings.json | 6 +++ .../DesignTimeTextMatcherContextFactory.cs | 21 ----------- .../Nocr.Users.Persistence.csproj | 8 ---- src/Nocr.Users.Persistence/appsettings.json | 5 --- 15 files changed, 145 insertions(+), 38 deletions(-) create mode 100755 src/Nocr.Users.Migrator/AddMigration.sh create mode 100644 src/Nocr.Users.Migrator/DesignTimeTextMatcherContextFactory.cs create mode 100644 src/Nocr.Users.Migrator/Dockerfile rename src/{Nocr.Users.Persistence/Migrations/20240330070727_InitialMigration.Designer.cs => Nocr.Users.Migrator/Migrations/20240330083951_InitialMigration.Designer.cs} (97%) rename src/{Nocr.Users.Persistence/Migrations/20240330070727_InitialMigration.cs => Nocr.Users.Migrator/Migrations/20240330083951_InitialMigration.cs} (98%) rename src/{Nocr.Users.Persistence => Nocr.Users.Migrator}/Migrations/UsersContextModelSnapshot.cs (98%) create mode 100644 src/Nocr.Users.Migrator/Nocr.Users.Migrator.csproj create mode 100644 src/Nocr.Users.Migrator/Program.cs create mode 100644 src/Nocr.Users.Migrator/Readme.md create mode 100644 src/Nocr.Users.Migrator/appsettings.json delete mode 100644 src/Nocr.Users.Persistence/DesignTimeTextMatcherContextFactory.cs delete mode 100644 src/Nocr.Users.Persistence/appsettings.json diff --git a/Directory.Packages.props b/Directory.Packages.props index 0830b7f..951fe88 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -18,7 +18,9 @@ + + diff --git a/Nocr.Users.sln b/Nocr.Users.sln index 1785430..87886bc 100644 --- a/Nocr.Users.sln +++ b/Nocr.Users.sln @@ -20,6 +20,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Contracts", "Contracts", "{ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nocr.Users.Persistence", "src\Nocr.Users.Persistence\Nocr.Users.Persistence.csproj", "{51C01BA8-E3E1-45F4-9DDF-6E08DAF5BB46}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nocr.Users.Migrator", "src\Nocr.Users.Migrator\Nocr.Users.Migrator.csproj", "{BA022CCE-FCAA-41E6-993D-B0794BBD0ECA}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -46,6 +48,10 @@ Global {51C01BA8-E3E1-45F4-9DDF-6E08DAF5BB46}.Debug|Any CPU.Build.0 = Debug|Any CPU {51C01BA8-E3E1-45F4-9DDF-6E08DAF5BB46}.Release|Any CPU.ActiveCfg = Release|Any CPU {51C01BA8-E3E1-45F4-9DDF-6E08DAF5BB46}.Release|Any CPU.Build.0 = Release|Any CPU + {BA022CCE-FCAA-41E6-993D-B0794BBD0ECA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BA022CCE-FCAA-41E6-993D-B0794BBD0ECA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BA022CCE-FCAA-41E6-993D-B0794BBD0ECA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BA022CCE-FCAA-41E6-993D-B0794BBD0ECA}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {4DDFB05F-DFC7-4BD6-B593-AD52CF1B002E} = {CA3AA87B-9217-4A2D-9EBA-BFC415B63818} diff --git a/src/Nocr.Users.Migrator/AddMigration.sh b/src/Nocr.Users.Migrator/AddMigration.sh new file mode 100755 index 0000000..bcd67f2 --- /dev/null +++ b/src/Nocr.Users.Migrator/AddMigration.sh @@ -0,0 +1,2 @@ +export DOTNET_ENVIRONMENT=Development +dotnet ef migrations add $1 diff --git a/src/Nocr.Users.Migrator/DesignTimeTextMatcherContextFactory.cs b/src/Nocr.Users.Migrator/DesignTimeTextMatcherContextFactory.cs new file mode 100644 index 0000000..b6500ab --- /dev/null +++ b/src/Nocr.Users.Migrator/DesignTimeTextMatcherContextFactory.cs @@ -0,0 +1,37 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Design; +using Microsoft.Extensions.Configuration; +using Nocr.Users.Persistence; + +namespace Nocr.Users.Migrator; + +public class DesignTimeTextMatcherContextFactory : IDesignTimeDbContextFactory +{ + private const string EnvironmentVariableKey = "DOTNET_ENVIRONMENT"; + + public UsersContext CreateDbContext(string[] args) + { + var optionsBuilder = new DbContextOptionsBuilder(); + + var configuration = new ConfigurationBuilder() + .SetBasePath(AppDomain.CurrentDomain.BaseDirectory) + .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) + .AddEnvironmentVariables() + .Build(); + + var environment = configuration.GetValue(EnvironmentVariableKey); + if (string.IsNullOrWhiteSpace(environment)) + { + throw new InvalidOperationException($"Отсутствует переменная окружения {EnvironmentVariableKey}"); + } + + var connectionString = configuration.GetConnectionString(environment); + if (string.IsNullOrWhiteSpace(connectionString)) + throw new InvalidOperationException($"ConnectionString for environment `{environment}` not found"); + + optionsBuilder.UseMySql(connectionString, new MariaDbServerVersion(MariaDbServerVersion.LatestSupportedServerVersion), + builder => builder.MigrationsAssembly("Nocr.Users.Migrator")); + + return new UsersContext(optionsBuilder.Options); + } +} \ No newline at end of file diff --git a/src/Nocr.Users.Migrator/Dockerfile b/src/Nocr.Users.Migrator/Dockerfile new file mode 100644 index 0000000..054cf8f --- /dev/null +++ b/src/Nocr.Users.Migrator/Dockerfile @@ -0,0 +1,19 @@ +FROM mcr.microsoft.com/dotnet/runtime:8.0 AS base +WORKDIR /app + +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +WORKDIR /src +COPY . . + +RUN dotnet nuget add source -n "musk.fun.nocr" "https://gitea.musk.fun/api/packages/nocr/nuget/index.json" +RUN dotnet restore "src/Nocr.Users.Migrator/Nocr.Users.Migrator.csproj" +WORKDIR "/src/src/Nocr.Users.Migrator" +RUN dotnet build "Nocr.Users.Migrator.csproj" -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "Nocr.Users.Migrator.csproj" -c Release -o /app/publish + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "Nocr.Users.Migrator.dll"] diff --git a/src/Nocr.Users.Persistence/Migrations/20240330070727_InitialMigration.Designer.cs b/src/Nocr.Users.Migrator/Migrations/20240330083951_InitialMigration.Designer.cs similarity index 97% rename from src/Nocr.Users.Persistence/Migrations/20240330070727_InitialMigration.Designer.cs rename to src/Nocr.Users.Migrator/Migrations/20240330083951_InitialMigration.Designer.cs index 464c975..1f6e9b9 100644 --- a/src/Nocr.Users.Persistence/Migrations/20240330070727_InitialMigration.Designer.cs +++ b/src/Nocr.Users.Migrator/Migrations/20240330083951_InitialMigration.Designer.cs @@ -8,10 +8,10 @@ using Nocr.Users.Persistence; #nullable disable -namespace Nocr.Users.Persistence.Migrations +namespace Nocr.Users.Migrator.Migrations { [DbContext(typeof(UsersContext))] - [Migration("20240330070727_InitialMigration")] + [Migration("20240330083951_InitialMigration")] partial class InitialMigration { /// diff --git a/src/Nocr.Users.Persistence/Migrations/20240330070727_InitialMigration.cs b/src/Nocr.Users.Migrator/Migrations/20240330083951_InitialMigration.cs similarity index 98% rename from src/Nocr.Users.Persistence/Migrations/20240330070727_InitialMigration.cs rename to src/Nocr.Users.Migrator/Migrations/20240330083951_InitialMigration.cs index 0ce86a2..f575d34 100644 --- a/src/Nocr.Users.Persistence/Migrations/20240330070727_InitialMigration.cs +++ b/src/Nocr.Users.Migrator/Migrations/20240330083951_InitialMigration.cs @@ -3,7 +3,7 @@ using Microsoft.EntityFrameworkCore.Migrations; #nullable disable -namespace Nocr.Users.Persistence.Migrations +namespace Nocr.Users.Migrator.Migrations { /// public partial class InitialMigration : Migration diff --git a/src/Nocr.Users.Persistence/Migrations/UsersContextModelSnapshot.cs b/src/Nocr.Users.Migrator/Migrations/UsersContextModelSnapshot.cs similarity index 98% rename from src/Nocr.Users.Persistence/Migrations/UsersContextModelSnapshot.cs rename to src/Nocr.Users.Migrator/Migrations/UsersContextModelSnapshot.cs index 353423a..5bd08d9 100644 --- a/src/Nocr.Users.Persistence/Migrations/UsersContextModelSnapshot.cs +++ b/src/Nocr.Users.Migrator/Migrations/UsersContextModelSnapshot.cs @@ -7,7 +7,7 @@ using Nocr.Users.Persistence; #nullable disable -namespace Nocr.Users.Persistence.Migrations +namespace Nocr.Users.Migrator.Migrations { [DbContext(typeof(UsersContext))] partial class UsersContextModelSnapshot : ModelSnapshot diff --git a/src/Nocr.Users.Migrator/Nocr.Users.Migrator.csproj b/src/Nocr.Users.Migrator/Nocr.Users.Migrator.csproj new file mode 100644 index 0000000..f4f9028 --- /dev/null +++ b/src/Nocr.Users.Migrator/Nocr.Users.Migrator.csproj @@ -0,0 +1,37 @@ + + + + Exe + false + Linux + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + .dockerignore + + + Always + + + + + + + + diff --git a/src/Nocr.Users.Migrator/Program.cs b/src/Nocr.Users.Migrator/Program.cs new file mode 100644 index 0000000..1cfc3d0 --- /dev/null +++ b/src/Nocr.Users.Migrator/Program.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore; + +namespace Nocr.Users.Migrator; + +public class Program +{ + public static async Task Main(string[] args) + { + var contextFactory = new DesignTimeTextMatcherContextFactory(); + using (var context = contextFactory.CreateDbContext(Array.Empty())) + { + await context.Database.MigrateAsync(); + await context.SaveChangesAsync(); + var appliedMigrations = await context.Database.GetAppliedMigrationsAsync(); + Console.WriteLine("Applied migrations:"); + foreach (var appliedMigration in appliedMigrations) + { + Console.WriteLine(appliedMigration); + } + } + } +} \ No newline at end of file diff --git a/src/Nocr.Users.Migrator/Readme.md b/src/Nocr.Users.Migrator/Readme.md new file mode 100644 index 0000000..205ee9e --- /dev/null +++ b/src/Nocr.Users.Migrator/Readme.md @@ -0,0 +1,10 @@ +# Nocr.TextMatcher.Migrator + +Проект содержит консольное приложение для применения миграций к БД. +Для выбора строки подключения при запуске необходимо передать переменную окружения `DOTNET_ENVIRONMENT`. Для локальной разработки следует использовать `DOTNET_ENVIRONMENT=Development`. + +## Добавление миграций + +В приложении реализована логика выбора строки подключения, а dotnet ef не позволяет передать переменную окружения. Поэтому был создан скрипт AddMigration, который устанавливает значение `DOTNET_ENVIRONMENT=Development`. + +Пример использования: `./AddMigration MyMigration` \ No newline at end of file diff --git a/src/Nocr.Users.Migrator/appsettings.json b/src/Nocr.Users.Migrator/appsettings.json new file mode 100644 index 0000000..2cfb132 --- /dev/null +++ b/src/Nocr.Users.Migrator/appsettings.json @@ -0,0 +1,6 @@ +{ + "ConnectionStrings": { + "Development": "server=localhost;port=3307;database=nocr_users;uid=root;pwd=toor", + "DockerCompose": "server=nocr-users-db;port=3306;database=nocr_users;uid=root;pwd=toor" + } +} \ No newline at end of file diff --git a/src/Nocr.Users.Persistence/DesignTimeTextMatcherContextFactory.cs b/src/Nocr.Users.Persistence/DesignTimeTextMatcherContextFactory.cs deleted file mode 100644 index 4706c3c..0000000 --- a/src/Nocr.Users.Persistence/DesignTimeTextMatcherContextFactory.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Design; -using Microsoft.Extensions.Configuration; - -namespace Nocr.Users.Persistence; - -public class DesignTimeTextMatcherContextFactory : IDesignTimeDbContextFactory -{ - public UsersContext CreateDbContext(string[] args) - { - var optionsBuilder = new DbContextOptionsBuilder(); - var configuration = new ConfigurationBuilder() - .AddJsonFile("appsettings.json") - .Build(); - - var connectionString = configuration.GetConnectionString("MariaLocal"); - optionsBuilder.UseMySql(connectionString, new MariaDbServerVersion(MariaDbServerVersion.LatestSupportedServerVersion)); - - return new UsersContext(optionsBuilder.Options); - } -} \ No newline at end of file diff --git a/src/Nocr.Users.Persistence/Nocr.Users.Persistence.csproj b/src/Nocr.Users.Persistence/Nocr.Users.Persistence.csproj index 021cc7b..1abff41 100644 --- a/src/Nocr.Users.Persistence/Nocr.Users.Persistence.csproj +++ b/src/Nocr.Users.Persistence/Nocr.Users.Persistence.csproj @@ -9,18 +9,10 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - Always - - diff --git a/src/Nocr.Users.Persistence/appsettings.json b/src/Nocr.Users.Persistence/appsettings.json deleted file mode 100644 index 62bb122..0000000 --- a/src/Nocr.Users.Persistence/appsettings.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "ConnectionStrings": { - "MariaLocal": "server=localhost;port=3307;database=nocr_users;uid=root;pwd=toor" - } -} \ No newline at end of file