diff --git a/Directory.Packages.props b/Directory.Packages.props
index 0ffdc0f..ea615f3 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -25,9 +25,11 @@
+
+
+
-
diff --git a/Nocr.TextMatcher.sln b/Nocr.TextMatcher.sln
index d698a8a..d93c47d 100644
--- a/Nocr.TextMatcher.sln
+++ b/Nocr.TextMatcher.sln
@@ -28,6 +28,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nocr.TextMatcher.Persistenc
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Contracts", "Contracts", "{0B8E28B3-EECC-4981-A87F-6D74C4F23371}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nocr.TextMatcher.Migrator", "src\Nocr.TextMatcher.Migrator\Nocr.TextMatcher.Migrator.csproj", "{6C429E86-0344-40C2-8898-BBA551E50403}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -66,6 +68,10 @@ Global
{D578EE54-B55A-4B45-859D-7F343C73EEF5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D578EE54-B55A-4B45-859D-7F343C73EEF5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D578EE54-B55A-4B45-859D-7F343C73EEF5}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6C429E86-0344-40C2-8898-BBA551E50403}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6C429E86-0344-40C2-8898-BBA551E50403}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6C429E86-0344-40C2-8898-BBA551E50403}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6C429E86-0344-40C2-8898-BBA551E50403}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{B721E055-84AF-44C6-973D-33241FD2EA7C} = {6E4D9F75-861F-4C00-A5C8-00D1BEE5A659}
diff --git a/src/Nocr.TextMatcher.Migrator/AddMigration.sh b/src/Nocr.TextMatcher.Migrator/AddMigration.sh
new file mode 100755
index 0000000..f6b37a3
--- /dev/null
+++ b/src/Nocr.TextMatcher.Migrator/AddMigration.sh
@@ -0,0 +1,2 @@
+export DOTNET_ENVIRONMNET=Development
+dotnet ef migrations add $1
diff --git a/src/Nocr.TextMatcher.Migrator/DesignTimeTextMatcherContextFactory.cs b/src/Nocr.TextMatcher.Migrator/DesignTimeTextMatcherContextFactory.cs
new file mode 100644
index 0000000..fef3c26
--- /dev/null
+++ b/src/Nocr.TextMatcher.Migrator/DesignTimeTextMatcherContextFactory.cs
@@ -0,0 +1,37 @@
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Design;
+using Microsoft.Extensions.Configuration;
+using Nocr.TextMatcher.Persistence;
+
+namespace Nocr.TextMatcher.Migrator;
+
+public class DesignTimeTextMatcherContextFactory : IDesignTimeDbContextFactory
+{
+ private const string EnvironmentVariableKey = "DOTNET_ENVIRONMENT";
+
+ public TextMatcherContext 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.TextMatcher.Migrator"));
+
+ return new TextMatcherContext(optionsBuilder.Options);
+ }
+}
\ No newline at end of file
diff --git a/src/Nocr.TextMatcher.Migrator/Dockerfile b/src/Nocr.TextMatcher.Migrator/Dockerfile
new file mode 100644
index 0000000..d31b91f
--- /dev/null
+++ b/src/Nocr.TextMatcher.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.TextMatcher.Migrator/Nocr.TextMatcher.Migrator.csproj"
+WORKDIR "/src/src/Nocr.TextMatcher.Migrator"
+RUN dotnet build "Nocr.TextMatcher.Migrator.csproj" -c Release -o /app/build
+
+FROM build AS publish
+RUN dotnet publish "Nocr.TextMatcher.Migrator.csproj" -c Release -o /app/publish
+
+FROM base AS final
+WORKDIR /app
+COPY --from=publish /app/publish .
+ENTRYPOINT ["dotnet", "Nocr.TextMatcher.Migrator.dll"]
diff --git a/src/Nocr.TextMatcher.Persistence/Migrations/20240328201810_InitialMigration.Designer.cs b/src/Nocr.TextMatcher.Migrator/Migrations/20240330082504_InitialMigration.Designer.cs
similarity index 93%
rename from src/Nocr.TextMatcher.Persistence/Migrations/20240328201810_InitialMigration.Designer.cs
rename to src/Nocr.TextMatcher.Migrator/Migrations/20240330082504_InitialMigration.Designer.cs
index e443aa6..9b77d01 100644
--- a/src/Nocr.TextMatcher.Persistence/Migrations/20240328201810_InitialMigration.Designer.cs
+++ b/src/Nocr.TextMatcher.Migrator/Migrations/20240330082504_InitialMigration.Designer.cs
@@ -9,10 +9,10 @@ using Nocr.TextMatcher.Persistence;
#nullable disable
-namespace Nocr.TextMatcher.Persistence.Migrations
+namespace Nocr.TextMatcher.Migrator.Migrations
{
[DbContext(typeof(TextMatcherContext))]
- [Migration("20240328201810_InitialMigration")]
+ [Migration("20240330082504_InitialMigration")]
partial class InitialMigration
{
///
@@ -25,7 +25,7 @@ namespace Nocr.TextMatcher.Persistence.Migrations
MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);
- modelBuilder.Entity("Nocr.TextMatcher.AppServices.TextMatches.TextSubscription", b =>
+ modelBuilder.Entity("Nocr.TextMatcher.AppServices.TextSubscriptions.TextSubscription", b =>
{
b.Property("Id")
.ValueGeneratedOnAdd()
diff --git a/src/Nocr.TextMatcher.Persistence/Migrations/20240328201810_InitialMigration.cs b/src/Nocr.TextMatcher.Migrator/Migrations/20240330082504_InitialMigration.cs
similarity index 97%
rename from src/Nocr.TextMatcher.Persistence/Migrations/20240328201810_InitialMigration.cs
rename to src/Nocr.TextMatcher.Migrator/Migrations/20240330082504_InitialMigration.cs
index 7d7822b..50f58c7 100644
--- a/src/Nocr.TextMatcher.Persistence/Migrations/20240328201810_InitialMigration.cs
+++ b/src/Nocr.TextMatcher.Migrator/Migrations/20240330082504_InitialMigration.cs
@@ -4,7 +4,7 @@ using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
-namespace Nocr.TextMatcher.Persistence.Migrations
+namespace Nocr.TextMatcher.Migrator.Migrations
{
///
public partial class InitialMigration : Migration
diff --git a/src/Nocr.TextMatcher.Persistence/Migrations/TextMatcherContextModelSnapshot.cs b/src/Nocr.TextMatcher.Migrator/Migrations/TextMatcherContextModelSnapshot.cs
similarity index 95%
rename from src/Nocr.TextMatcher.Persistence/Migrations/TextMatcherContextModelSnapshot.cs
rename to src/Nocr.TextMatcher.Migrator/Migrations/TextMatcherContextModelSnapshot.cs
index 5dced80..3d22638 100644
--- a/src/Nocr.TextMatcher.Persistence/Migrations/TextMatcherContextModelSnapshot.cs
+++ b/src/Nocr.TextMatcher.Migrator/Migrations/TextMatcherContextModelSnapshot.cs
@@ -8,7 +8,7 @@ using Nocr.TextMatcher.Persistence;
#nullable disable
-namespace Nocr.TextMatcher.Persistence.Migrations
+namespace Nocr.TextMatcher.Migrator.Migrations
{
[DbContext(typeof(TextMatcherContext))]
partial class TextMatcherContextModelSnapshot : ModelSnapshot
@@ -22,7 +22,7 @@ namespace Nocr.TextMatcher.Persistence.Migrations
MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);
- modelBuilder.Entity("Nocr.TextMatcher.AppServices.TextMatches.TextSubscription", b =>
+ modelBuilder.Entity("Nocr.TextMatcher.AppServices.TextSubscriptions.TextSubscription", b =>
{
b.Property("Id")
.ValueGeneratedOnAdd()
diff --git a/src/Nocr.TextMatcher.Migrator/Nocr.TextMatcher.Migrator.csproj b/src/Nocr.TextMatcher.Migrator/Nocr.TextMatcher.Migrator.csproj
new file mode 100644
index 0000000..769e9ce
--- /dev/null
+++ b/src/Nocr.TextMatcher.Migrator/Nocr.TextMatcher.Migrator.csproj
@@ -0,0 +1,38 @@
+
+
+
+ Exe
+ false
+ Linux
+
+
+
+
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+ .dockerignore
+
+
+
+ Always
+
+
+
+
+
+
+
+
diff --git a/src/Nocr.TextMatcher.Migrator/Program.cs b/src/Nocr.TextMatcher.Migrator/Program.cs
new file mode 100644
index 0000000..62d28e0
--- /dev/null
+++ b/src/Nocr.TextMatcher.Migrator/Program.cs
@@ -0,0 +1,22 @@
+using Microsoft.EntityFrameworkCore;
+
+namespace Nocr.TextMatcher.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.TextMatcher.Migrator/Readme.md b/src/Nocr.TextMatcher.Migrator/Readme.md
new file mode 100644
index 0000000..205ee9e
--- /dev/null
+++ b/src/Nocr.TextMatcher.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.TextMatcher.Migrator/appsettings.json b/src/Nocr.TextMatcher.Migrator/appsettings.json
new file mode 100644
index 0000000..d6d0aba
--- /dev/null
+++ b/src/Nocr.TextMatcher.Migrator/appsettings.json
@@ -0,0 +1,6 @@
+{
+ "ConnectionStrings": {
+ "Development": "server=localhost;port=3306;database=nocr_text_matcher;uid=root;pwd=toor",
+ "DockerCompose": "server=nocr-text-matcher-db;port=3306;database=nocr_text_matcher;uid=root;pwd=toor"
+ }
+}
\ No newline at end of file
diff --git a/src/Nocr.TextMatcher.Persistence/DesignTimeTextMatcherContextFactory.cs b/src/Nocr.TextMatcher.Persistence/DesignTimeTextMatcherContextFactory.cs
deleted file mode 100644
index a419121..0000000
--- a/src/Nocr.TextMatcher.Persistence/DesignTimeTextMatcherContextFactory.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Design;
-using Microsoft.Extensions.Configuration;
-
-namespace Nocr.TextMatcher.Persistence;
-
-public class DesignTimeTextMatcherContextFactory : IDesignTimeDbContextFactory
-{
- public TextMatcherContext 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 TextMatcherContext(optionsBuilder.Options);
- }
-}
\ No newline at end of file
diff --git a/src/Nocr.TextMatcher.Persistence/Nocr.TextMatcher.Persistence.csproj b/src/Nocr.TextMatcher.Persistence/Nocr.TextMatcher.Persistence.csproj
index 348a1f4..6b3d97f 100644
--- a/src/Nocr.TextMatcher.Persistence/Nocr.TextMatcher.Persistence.csproj
+++ b/src/Nocr.TextMatcher.Persistence/Nocr.TextMatcher.Persistence.csproj
@@ -10,8 +10,6 @@
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
@@ -19,11 +17,4 @@
-
-
-
- Always
-
-
-
diff --git a/src/Nocr.TextMatcher.Persistence/ServiceCollectionExtensions.cs b/src/Nocr.TextMatcher.Persistence/ServiceCollectionExtensions.cs
index dd63d31..d2be272 100644
--- a/src/Nocr.TextMatcher.Persistence/ServiceCollectionExtensions.cs
+++ b/src/Nocr.TextMatcher.Persistence/ServiceCollectionExtensions.cs
@@ -21,8 +21,7 @@ public static class ServiceCollectionExtensions
services.AddDbContext(
(ctx, context) =>
{
- context.UseMySql(connectionString, new MariaDbServerVersion(MariaDbServerVersion.LatestSupportedServerVersion),
- builder => builder.MigrationsAssembly(typeof(TextMatcherContext).Assembly.FullName))
+ context.UseMySql(connectionString, new MariaDbServerVersion(MariaDbServerVersion.LatestSupportedServerVersion))
.UseLoggerFactory(ctx.GetRequiredService());
}
);
diff --git a/src/Nocr.TextMatcher.Persistence/appsettings.json b/src/Nocr.TextMatcher.Persistence/appsettings.json
deleted file mode 100644
index 78c0e88..0000000
--- a/src/Nocr.TextMatcher.Persistence/appsettings.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "ConnectionStrings": {
- "MariaLocal": "server=localhost;port=3306;database=nocr_text_matcher;uid=root;pwd=toor"
- }
-}
\ No newline at end of file