From b2ed6d43ef29f8e3d51af710c0f7dfbaa9f32060 Mon Sep 17 00:00:00 2001 From: "pa.pecherskij" Date: Tue, 30 Sep 2025 13:54:15 +0300 Subject: [PATCH 1/2] refactor: migrator app --- ...eller.SQLiteToPostgres.DataMigrator.csproj | 37 +++++++++ .../Program.cs | 79 +++++++++++++++++++ .../appsettings.json | 6 ++ SS14.Labeller.sln | 6 ++ 4 files changed, 128 insertions(+) create mode 100644 Labeller.SQLiteToPostgres.DataMigrator/Labeller.SQLiteToPostgres.DataMigrator.csproj create mode 100644 Labeller.SQLiteToPostgres.DataMigrator/Program.cs create mode 100644 Labeller.SQLiteToPostgres.DataMigrator/appsettings.json diff --git a/Labeller.SQLiteToPostgres.DataMigrator/Labeller.SQLiteToPostgres.DataMigrator.csproj b/Labeller.SQLiteToPostgres.DataMigrator/Labeller.SQLiteToPostgres.DataMigrator.csproj new file mode 100644 index 0000000..3eb1bbc --- /dev/null +++ b/Labeller.SQLiteToPostgres.DataMigrator/Labeller.SQLiteToPostgres.DataMigrator.csproj @@ -0,0 +1,37 @@ + + + + Exe + net9.0 + enable + enable + + + + + PreserveNewest + true + PreserveNewest + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + + diff --git a/Labeller.SQLiteToPostgres.DataMigrator/Program.cs b/Labeller.SQLiteToPostgres.DataMigrator/Program.cs new file mode 100644 index 0000000..68fd29a --- /dev/null +++ b/Labeller.SQLiteToPostgres.DataMigrator/Program.cs @@ -0,0 +1,79 @@ +using Dapper; +using Microsoft.Data.Sqlite; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using SS14.Labeller.Database; +using SS14.Labeller.Database.Entities; + +IConfiguration configuration = new ConfigurationBuilder() + .SetBasePath(Directory.GetCurrentDirectory()) + .AddJsonFile("appsettings.json") + .AddEnvironmentVariables() + .AddCommandLine(args) + .Build(); + +var pgConnectionString = configuration.GetConnectionString("Postgres") + ?? throw new InvalidOperationException( + "Failed to find 'Default' connection string " + + "from application configuration for database initialization." + ); + +var sqliteConnectionString = configuration.GetConnectionString("Sqlite") + ?? throw new InvalidOperationException( + "Failed to find 'Default' connection string " + + "from application configuration for database initialization." + ); + +var serviceCollection = new ServiceCollection(); + +serviceCollection.AddPooledDbContextFactory( + optsBuilder => optsBuilder.UseNpgsql(pgConnectionString) + .UseSnakeCaseNamingConvention() +); + +serviceCollection.AddSingleton(); + +var sp = serviceCollection.BuildServiceProvider(); + +await using var sqliteConnections = new SqliteConnection(sqliteConnectionString); +sqliteConnections.Open(); + +var existingRecords = await sqliteConnections.QueryAsync( + """ + SELECT + DiscussionId + ,RepoOwner + ,RepoName + ,IssueNumber + ,TopicId + FROM Discussions + """ +); + +var contextFactory = sp.GetRequiredService>(); +using var context = contextFactory.CreateDbContext(); +context.Database.EnsureCreated(); + +var mapped = existingRecords.Select(x => new DiscourseTopicEntity +{ + Id = x.DiscussionId, + RepoOwner = x.RepoOwner, + RepoName = x.RepoName, + IssueNumber = x.IssueNumber, + TopicId = x.TopicId, + +}).ToArray(); +await context.Set() + .AddRangeAsync(mapped); + +await context.SaveChangesAsync(); + +public record DiscourseTopicDbModel +{ + public int DiscussionId {get;set;} + public string RepoOwner {get;set;} + public string RepoName {get;set;} + public int IssueNumber {get;set;} + public int TopicId { get; set; } +} diff --git a/Labeller.SQLiteToPostgres.DataMigrator/appsettings.json b/Labeller.SQLiteToPostgres.DataMigrator/appsettings.json new file mode 100644 index 0000000..3203bad --- /dev/null +++ b/Labeller.SQLiteToPostgres.DataMigrator/appsettings.json @@ -0,0 +1,6 @@ +{ + "ConnectionStrings": { + "Postgres": "Host=localhost;Port=5432;Username=postgres;Password=postgres;Database=labeller;", + "Sqlite": "Data Source=data/Application.db" + } +} \ No newline at end of file diff --git a/SS14.Labeller.sln b/SS14.Labeller.sln index 8defc13..6e38bab 100644 --- a/SS14.Labeller.sln +++ b/SS14.Labeller.sln @@ -15,6 +15,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SS14.Labeller.Tests", "SS14.Labeller.Tests\SS14.Labeller.Tests.csproj", "{E6AD98D5-0330-4056-9042-B8DB3F569B38}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Labeller.SQLiteToPostgres.DataMigrator", "Labeller.SQLiteToPostgres.DataMigrator\Labeller.SQLiteToPostgres.DataMigrator.csproj", "{9A4858F0-2F41-44DF-BFA1-1C1131F8F0AA}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -29,6 +31,10 @@ Global {E6AD98D5-0330-4056-9042-B8DB3F569B38}.Debug|Any CPU.Build.0 = Debug|Any CPU {E6AD98D5-0330-4056-9042-B8DB3F569B38}.Release|Any CPU.ActiveCfg = Release|Any CPU {E6AD98D5-0330-4056-9042-B8DB3F569B38}.Release|Any CPU.Build.0 = Release|Any CPU + {9A4858F0-2F41-44DF-BFA1-1C1131F8F0AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9A4858F0-2F41-44DF-BFA1-1C1131F8F0AA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9A4858F0-2F41-44DF-BFA1-1C1131F8F0AA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9A4858F0-2F41-44DF-BFA1-1C1131F8F0AA}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 53c3043404a7445d65f99f0b88267b80b13ce817 Mon Sep 17 00:00:00 2001 From: "pa.pecherskij" Date: Thu, 9 Oct 2025 14:36:00 +0300 Subject: [PATCH 2/2] refactor: fix migrator not adding records to __EFMigrationsHistory --- Labeller.SQLiteToPostgres.DataMigrator/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Labeller.SQLiteToPostgres.DataMigrator/Program.cs b/Labeller.SQLiteToPostgres.DataMigrator/Program.cs index 68fd29a..f44f614 100644 --- a/Labeller.SQLiteToPostgres.DataMigrator/Program.cs +++ b/Labeller.SQLiteToPostgres.DataMigrator/Program.cs @@ -53,7 +53,7 @@ FROM Discussions var contextFactory = sp.GetRequiredService>(); using var context = contextFactory.CreateDbContext(); -context.Database.EnsureCreated(); +context.Database.Migrate(); var mapped = existingRecords.Select(x => new DiscourseTopicEntity {