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..f44f614
--- /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.Migrate();
+
+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