From 3c809de5dc8b012134b4c94b86cfebdf57c9d410 Mon Sep 17 00:00:00 2001
From: Stevan Freeborn <65925598+StevanFreeborn@users.noreply.github.com>
Date: Sun, 18 Aug 2024 20:16:38 -0500
Subject: [PATCH] feat: work on setting up database
---
.vscode/launch.json | 21 ++
.vscode/settings.json | 6 +-
.vscode/tasks.json | 41 ++++
...240819001854_initial_migration.Designer.cs | 197 ++++++++++++++++++
.../20240819001854_initial_migration.cs | 133 ++++++++++++
.../Migrations/AppDbContextModelSnapshot.cs | 194 +++++++++++++++++
src/SanctionsSearch.Worker/Models/Address.cs | 13 ++
src/SanctionsSearch.Worker/Models/Alias.cs | 12 ++
src/SanctionsSearch.Worker/Models/Comment.cs | 10 +
src/SanctionsSearch.Worker/Models/Sdn.cs | 19 ++
.../Options/DbOptions.cs | 6 +
.../Persistence/AppDbContext.cs | 40 ++++
src/SanctionsSearch.Worker/Program.cs | 25 +++
.../SanctionsSearch.Worker.csproj | 5 +
.../SanctionsSearch.dev.db | Bin 0 -> 45056 bytes
.../Setup/DbOptionsSetup.cs | 9 +
.../Setup/OfacFileServiceOptionsSetup.cs | 9 +
src/SanctionsSearch.Worker/Usings.cs | 3 +
.../appsettings.Example.json | 3 +
19 files changed, 745 insertions(+), 1 deletion(-)
create mode 100644 .vscode/launch.json
create mode 100644 .vscode/tasks.json
create mode 100644 src/SanctionsSearch.Worker/Migrations/20240819001854_initial_migration.Designer.cs
create mode 100644 src/SanctionsSearch.Worker/Migrations/20240819001854_initial_migration.cs
create mode 100644 src/SanctionsSearch.Worker/Migrations/AppDbContextModelSnapshot.cs
create mode 100644 src/SanctionsSearch.Worker/Models/Address.cs
create mode 100644 src/SanctionsSearch.Worker/Models/Alias.cs
create mode 100644 src/SanctionsSearch.Worker/Models/Comment.cs
create mode 100644 src/SanctionsSearch.Worker/Models/Sdn.cs
create mode 100644 src/SanctionsSearch.Worker/Options/DbOptions.cs
create mode 100644 src/SanctionsSearch.Worker/Persistence/AppDbContext.cs
create mode 100644 src/SanctionsSearch.Worker/SanctionsSearch.dev.db
create mode 100644 src/SanctionsSearch.Worker/Setup/DbOptionsSetup.cs
create mode 100644 src/SanctionsSearch.Worker/Setup/OfacFileServiceOptionsSetup.cs
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000..2abff29
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,21 @@
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "Worker",
+ "type": "coreclr",
+ "request": "launch",
+ "preLaunchTask": "build",
+ "program": "${workspaceFolder}/src/SanctionsSearch.Worker/bin/Debug/net8.0/SanctionsSearch.Worker.dll",
+ "args": [],
+ "cwd": "${workspaceFolder}/src/SanctionsSearch.Worker",
+ "console": "internalConsole",
+ "stopAtEntry": false
+ },
+ {
+ "name": ".NET Core Attach",
+ "type": "coreclr",
+ "request": "attach"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 578cdda..9bd4323 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,5 +1,9 @@
{
"editor.formatOnSave": true,
"dotnet.defaultSolution": "src/SanctionsSearch.sln",
- "cSpell.words": ["OFAC", "Szalay"]
+ "cSpell.words": [
+ "OFAC",
+ "Sdns",
+ "Szalay"
+ ]
}
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
new file mode 100644
index 0000000..0db3584
--- /dev/null
+++ b/.vscode/tasks.json
@@ -0,0 +1,41 @@
+{
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "label": "build",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "build",
+ "${workspaceFolder}/src/SanctionsSearch.sln",
+ "/property:GenerateFullPaths=true",
+ "/consoleloggerparameters:NoSummary;ForceNoAlign"
+ ],
+ "problemMatcher": "$msCompile"
+ },
+ {
+ "label": "publish",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "publish",
+ "${workspaceFolder}/src/SanctionsSearch.sln",
+ "/property:GenerateFullPaths=true",
+ "/consoleloggerparameters:NoSummary;ForceNoAlign"
+ ],
+ "problemMatcher": "$msCompile"
+ },
+ {
+ "label": "watch",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "watch",
+ "run",
+ "--project",
+ "${workspaceFolder}/src/SanctionsSearch.sln"
+ ],
+ "problemMatcher": "$msCompile"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/SanctionsSearch.Worker/Migrations/20240819001854_initial_migration.Designer.cs b/src/SanctionsSearch.Worker/Migrations/20240819001854_initial_migration.Designer.cs
new file mode 100644
index 0000000..0b47d27
--- /dev/null
+++ b/src/SanctionsSearch.Worker/Migrations/20240819001854_initial_migration.Designer.cs
@@ -0,0 +1,197 @@
+//
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using SanctionsSearch.Worker.Persistence;
+
+#nullable disable
+
+namespace SanctionsSearch.Worker.Migrations
+{
+ [DbContext(typeof(AppDbContext))]
+ [Migration("20240819001854_initial_migration")]
+ partial class initial_migration
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder.HasAnnotation("ProductVersion", "8.0.8");
+
+ modelBuilder.Entity("SanctionsSearch.Worker.Models.Address", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("CityProvincePostal")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("Country")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("Remarks")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("SdnId")
+ .HasColumnType("INTEGER");
+
+ b.Property("StreetAddress")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.HasIndex("SdnId");
+
+ b.ToTable("Addresses");
+ });
+
+ modelBuilder.Entity("SanctionsSearch.Worker.Models.Alias", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("Remarks")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("SdnId")
+ .HasColumnType("INTEGER");
+
+ b.Property("Type")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.HasIndex("SdnId");
+
+ b.ToTable("Aliases");
+ });
+
+ modelBuilder.Entity("SanctionsSearch.Worker.Models.Comment", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("Remarks")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("SdnId")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.HasIndex("SdnId");
+
+ b.ToTable("Comments");
+ });
+
+ modelBuilder.Entity("SanctionsSearch.Worker.Models.Sdn", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("CallSign")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("GrossRegisteredTonnage")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("Program")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("Remarks")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("Title")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("Tonnage")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("Type")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("VesselFlag")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("VesselOwner")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("VesselType")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.ToTable("Sdns");
+ });
+
+ modelBuilder.Entity("SanctionsSearch.Worker.Models.Address", b =>
+ {
+ b.HasOne("SanctionsSearch.Worker.Models.Sdn", "Sdn")
+ .WithMany()
+ .HasForeignKey("SdnId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Sdn");
+ });
+
+ modelBuilder.Entity("SanctionsSearch.Worker.Models.Alias", b =>
+ {
+ b.HasOne("SanctionsSearch.Worker.Models.Sdn", "Sdn")
+ .WithMany("Aliases")
+ .HasForeignKey("SdnId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Sdn");
+ });
+
+ modelBuilder.Entity("SanctionsSearch.Worker.Models.Comment", b =>
+ {
+ b.HasOne("SanctionsSearch.Worker.Models.Sdn", "Sdn")
+ .WithMany()
+ .HasForeignKey("SdnId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Sdn");
+ });
+
+ modelBuilder.Entity("SanctionsSearch.Worker.Models.Sdn", b =>
+ {
+ b.Navigation("Aliases");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/src/SanctionsSearch.Worker/Migrations/20240819001854_initial_migration.cs b/src/SanctionsSearch.Worker/Migrations/20240819001854_initial_migration.cs
new file mode 100644
index 0000000..4679dec
--- /dev/null
+++ b/src/SanctionsSearch.Worker/Migrations/20240819001854_initial_migration.cs
@@ -0,0 +1,133 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace SanctionsSearch.Worker.Migrations
+{
+ ///
+ public partial class initial_migration : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.CreateTable(
+ name: "Sdns",
+ columns: table => new
+ {
+ Id = table.Column(type: "INTEGER", nullable: false)
+ .Annotation("Sqlite:Autoincrement", true),
+ Name = table.Column(type: "TEXT", nullable: false),
+ Type = table.Column(type: "TEXT", nullable: false),
+ Program = table.Column(type: "TEXT", nullable: false),
+ Title = table.Column(type: "TEXT", nullable: false),
+ CallSign = table.Column(type: "TEXT", nullable: false),
+ VesselType = table.Column(type: "TEXT", nullable: false),
+ Tonnage = table.Column(type: "TEXT", nullable: false),
+ GrossRegisteredTonnage = table.Column(type: "TEXT", nullable: false),
+ VesselFlag = table.Column(type: "TEXT", nullable: false),
+ VesselOwner = table.Column(type: "TEXT", nullable: false),
+ Remarks = table.Column(type: "TEXT", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Sdns", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "Addresses",
+ columns: table => new
+ {
+ Id = table.Column(type: "INTEGER", nullable: false)
+ .Annotation("Sqlite:Autoincrement", true),
+ SdnId = table.Column(type: "INTEGER", nullable: false),
+ StreetAddress = table.Column(type: "TEXT", nullable: false),
+ CityProvincePostal = table.Column(type: "TEXT", nullable: false),
+ Country = table.Column(type: "TEXT", nullable: false),
+ Remarks = table.Column(type: "TEXT", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Addresses", x => x.Id);
+ table.ForeignKey(
+ name: "FK_Addresses_Sdns_SdnId",
+ column: x => x.SdnId,
+ principalTable: "Sdns",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "Aliases",
+ columns: table => new
+ {
+ Id = table.Column(type: "INTEGER", nullable: false)
+ .Annotation("Sqlite:Autoincrement", true),
+ SdnId = table.Column(type: "INTEGER", nullable: false),
+ Type = table.Column(type: "TEXT", nullable: false),
+ Name = table.Column(type: "TEXT", nullable: false),
+ Remarks = table.Column(type: "TEXT", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Aliases", x => x.Id);
+ table.ForeignKey(
+ name: "FK_Aliases_Sdns_SdnId",
+ column: x => x.SdnId,
+ principalTable: "Sdns",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "Comments",
+ columns: table => new
+ {
+ Id = table.Column(type: "INTEGER", nullable: false)
+ .Annotation("Sqlite:Autoincrement", true),
+ SdnId = table.Column(type: "INTEGER", nullable: false),
+ Remarks = table.Column(type: "TEXT", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Comments", x => x.Id);
+ table.ForeignKey(
+ name: "FK_Comments_Sdns_SdnId",
+ column: x => x.SdnId,
+ principalTable: "Sdns",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateIndex(
+ name: "IX_Addresses_SdnId",
+ table: "Addresses",
+ column: "SdnId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_Aliases_SdnId",
+ table: "Aliases",
+ column: "SdnId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_Comments_SdnId",
+ table: "Comments",
+ column: "SdnId");
+ }
+
+ ///
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropTable(
+ name: "Addresses");
+
+ migrationBuilder.DropTable(
+ name: "Aliases");
+
+ migrationBuilder.DropTable(
+ name: "Comments");
+
+ migrationBuilder.DropTable(
+ name: "Sdns");
+ }
+ }
+}
diff --git a/src/SanctionsSearch.Worker/Migrations/AppDbContextModelSnapshot.cs b/src/SanctionsSearch.Worker/Migrations/AppDbContextModelSnapshot.cs
new file mode 100644
index 0000000..7c079ac
--- /dev/null
+++ b/src/SanctionsSearch.Worker/Migrations/AppDbContextModelSnapshot.cs
@@ -0,0 +1,194 @@
+//
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using SanctionsSearch.Worker.Persistence;
+
+#nullable disable
+
+namespace SanctionsSearch.Worker.Migrations
+{
+ [DbContext(typeof(AppDbContext))]
+ partial class AppDbContextModelSnapshot : ModelSnapshot
+ {
+ protected override void BuildModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder.HasAnnotation("ProductVersion", "8.0.8");
+
+ modelBuilder.Entity("SanctionsSearch.Worker.Models.Address", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("CityProvincePostal")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("Country")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("Remarks")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("SdnId")
+ .HasColumnType("INTEGER");
+
+ b.Property("StreetAddress")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.HasIndex("SdnId");
+
+ b.ToTable("Addresses");
+ });
+
+ modelBuilder.Entity("SanctionsSearch.Worker.Models.Alias", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("Remarks")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("SdnId")
+ .HasColumnType("INTEGER");
+
+ b.Property("Type")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.HasIndex("SdnId");
+
+ b.ToTable("Aliases");
+ });
+
+ modelBuilder.Entity("SanctionsSearch.Worker.Models.Comment", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("Remarks")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("SdnId")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.HasIndex("SdnId");
+
+ b.ToTable("Comments");
+ });
+
+ modelBuilder.Entity("SanctionsSearch.Worker.Models.Sdn", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("CallSign")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("GrossRegisteredTonnage")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("Program")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("Remarks")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("Title")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("Tonnage")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("Type")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("VesselFlag")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("VesselOwner")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("VesselType")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.ToTable("Sdns");
+ });
+
+ modelBuilder.Entity("SanctionsSearch.Worker.Models.Address", b =>
+ {
+ b.HasOne("SanctionsSearch.Worker.Models.Sdn", "Sdn")
+ .WithMany()
+ .HasForeignKey("SdnId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Sdn");
+ });
+
+ modelBuilder.Entity("SanctionsSearch.Worker.Models.Alias", b =>
+ {
+ b.HasOne("SanctionsSearch.Worker.Models.Sdn", "Sdn")
+ .WithMany("Aliases")
+ .HasForeignKey("SdnId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Sdn");
+ });
+
+ modelBuilder.Entity("SanctionsSearch.Worker.Models.Comment", b =>
+ {
+ b.HasOne("SanctionsSearch.Worker.Models.Sdn", "Sdn")
+ .WithMany()
+ .HasForeignKey("SdnId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Sdn");
+ });
+
+ modelBuilder.Entity("SanctionsSearch.Worker.Models.Sdn", b =>
+ {
+ b.Navigation("Aliases");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/src/SanctionsSearch.Worker/Models/Address.cs b/src/SanctionsSearch.Worker/Models/Address.cs
new file mode 100644
index 0000000..d4d9acc
--- /dev/null
+++ b/src/SanctionsSearch.Worker/Models/Address.cs
@@ -0,0 +1,13 @@
+namespace SanctionsSearch.Worker.Models;
+
+class Address
+{
+ public int SdnId { get; set; }
+ public int Id { get; set; }
+ public string StreetAddress { get; set; } = string.Empty;
+ public string CityProvincePostal { get; set; } = string.Empty;
+ public string Country { get; set; } = string.Empty;
+ public string Remarks { get; set; } = string.Empty;
+
+ public virtual Sdn Sdn { get; set; } = default!;
+}
\ No newline at end of file
diff --git a/src/SanctionsSearch.Worker/Models/Alias.cs b/src/SanctionsSearch.Worker/Models/Alias.cs
new file mode 100644
index 0000000..848d427
--- /dev/null
+++ b/src/SanctionsSearch.Worker/Models/Alias.cs
@@ -0,0 +1,12 @@
+namespace SanctionsSearch.Worker.Models;
+
+class Alias
+{
+ public int SdnId { get; set; }
+ public int Id { get; set; }
+ public string Type { get; set; } = string.Empty;
+ public string Name { get; set; } = string.Empty;
+ public string Remarks { get; set; } = string.Empty;
+
+ public virtual Sdn Sdn { get; set; } = default!;
+}
\ No newline at end of file
diff --git a/src/SanctionsSearch.Worker/Models/Comment.cs b/src/SanctionsSearch.Worker/Models/Comment.cs
new file mode 100644
index 0000000..b811d5d
--- /dev/null
+++ b/src/SanctionsSearch.Worker/Models/Comment.cs
@@ -0,0 +1,10 @@
+namespace SanctionsSearch.Worker.Models;
+
+class Comment
+{
+ public int SdnId { get; set; }
+ public int Id { get; set; }
+ public string Remarks { get; set; } = string.Empty;
+
+ public virtual Sdn Sdn { get; set; } = default!;
+}
\ No newline at end of file
diff --git a/src/SanctionsSearch.Worker/Models/Sdn.cs b/src/SanctionsSearch.Worker/Models/Sdn.cs
new file mode 100644
index 0000000..187380f
--- /dev/null
+++ b/src/SanctionsSearch.Worker/Models/Sdn.cs
@@ -0,0 +1,19 @@
+namespace SanctionsSearch.Worker.Models;
+
+class Sdn
+{
+ public int Id { get; set; }
+ public string Name { get; set; } = string.Empty;
+ public string Type { get; set; } = string.Empty;
+ public string Program { get; set; } = string.Empty;
+ public string Title { get; set; } = string.Empty;
+ public string CallSign { get; set; } = string.Empty;
+ public string VesselType { get; set; } = string.Empty;
+ public string Tonnage { get; set; } = string.Empty;
+ public string GrossRegisteredTonnage { get; set; } = string.Empty;
+ public string VesselFlag { get; set; } = string.Empty;
+ public string VesselOwner { get; set; } = string.Empty;
+ public string Remarks { get; set; } = string.Empty;
+
+ public virtual ICollection Aliases { get; set; } = [];
+}
\ No newline at end of file
diff --git a/src/SanctionsSearch.Worker/Options/DbOptions.cs b/src/SanctionsSearch.Worker/Options/DbOptions.cs
new file mode 100644
index 0000000..1d6fbea
--- /dev/null
+++ b/src/SanctionsSearch.Worker/Options/DbOptions.cs
@@ -0,0 +1,6 @@
+namespace SanctionsSearch.Worker.Options;
+
+class DbOptions
+{
+ public string DatabaseName { get; set; } = string.Empty;
+}
\ No newline at end of file
diff --git a/src/SanctionsSearch.Worker/Persistence/AppDbContext.cs b/src/SanctionsSearch.Worker/Persistence/AppDbContext.cs
new file mode 100644
index 0000000..440d86a
--- /dev/null
+++ b/src/SanctionsSearch.Worker/Persistence/AppDbContext.cs
@@ -0,0 +1,40 @@
+using System.Reflection;
+
+using Microsoft.Data.Sqlite;
+
+namespace SanctionsSearch.Worker.Persistence;
+
+class AppDbContext(IOptionsSnapshot options) : DbContext, IDisposable
+{
+ private readonly IOptionsSnapshot _options = options;
+ private SqliteConnection? _connection;
+ public DbSet Sdns { get; set; } = default!;
+ public DbSet Addresses { get; set; } = default!;
+ public DbSet Aliases { get; set; } = default!;
+ public DbSet Comments { get; set; } = default!;
+
+ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
+ {
+ var folder = Environment.SpecialFolder.LocalApplicationData;
+ var path = Environment.GetFolderPath(folder);
+ var dataDir = Path.Combine(path, "SanctionsSearch", "Data");
+
+ if (Directory.Exists(dataDir) == false)
+ {
+ Directory.CreateDirectory(dataDir);
+ }
+
+ var dbPath = Path.Combine(dataDir, _options.Value.DatabaseName);
+
+ _connection = new SqliteConnection($"Data Source={dbPath}");
+ _connection.Open();
+
+ optionsBuilder.UseSqlite(_connection);
+ }
+
+ public override void Dispose()
+ {
+ _connection?.Dispose();
+ base.Dispose();
+ }
+}
\ No newline at end of file
diff --git a/src/SanctionsSearch.Worker/Program.cs b/src/SanctionsSearch.Worker/Program.cs
index f910460..9161995 100644
--- a/src/SanctionsSearch.Worker/Program.cs
+++ b/src/SanctionsSearch.Worker/Program.cs
@@ -1,3 +1,12 @@
+using SanctionsSearch.Worker.Persistence;
+using SanctionsSearch.Worker.Setup;
+
+if (EF.IsDesignTime)
+{
+ Host.CreateDefaultBuilder().Build().Run();
+ return;
+}
+
Log.Logger = new LoggerConfiguration()
.Enrich.WithProperty("Application", "SanctionsSearch.Worker")
.Enrich.WithEnvironmentName()
@@ -19,9 +28,25 @@ try
builder.Logging.ClearProviders();
builder.Logging.AddSerilog();
+
+ builder.Services.ConfigureOptions();
+ builder.Services.ConfigureOptions();
+
+ builder.Services.AddDbContext();
builder.Services.AddHostedService();
var host = builder.Build();
+
+ using var scope = host.Services.CreateScope();
+ var context = scope.ServiceProvider.GetRequiredService();
+ var pendingMigrations = await context.Database.GetPendingMigrationsAsync();
+
+ if (pendingMigrations.Any())
+ {
+ Log.Information("Applying pending migrations");
+ await context.Database.MigrateAsync();
+ }
+
host.Run();
Log.Information("Stopping Sanctions Search worker");
diff --git a/src/SanctionsSearch.Worker/SanctionsSearch.Worker.csproj b/src/SanctionsSearch.Worker/SanctionsSearch.Worker.csproj
index f80e5c9..9143c2f 100644
--- a/src/SanctionsSearch.Worker/SanctionsSearch.Worker.csproj
+++ b/src/SanctionsSearch.Worker/SanctionsSearch.Worker.csproj
@@ -10,6 +10,11 @@
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
diff --git a/src/SanctionsSearch.Worker/SanctionsSearch.dev.db b/src/SanctionsSearch.Worker/SanctionsSearch.dev.db
new file mode 100644
index 0000000000000000000000000000000000000000..6e3bd43beb4c370a73e8772ae4dbfc15124f55d4
GIT binary patch
literal 45056
zcmeI)J#X7a7zc2k?TC^bRb2uOhT#LV*huO~X$rerS($Q$NR^fjtBa6EOl&ifl-_
zt%eS9`tnJ-6zG;u(xFp6K|Vo;4n0ady;)QsBuk_}AwqmPKF9k#ccM==-2S%iL^gfy
z2R$pIp9`M~ga}_zDhR>`TesQDmn_@Z;ydh}Ol+rZZU~3Z-xiAh3VHEN_~h^6UpN1|
z`R8^v_eVC&7RA@>AQlKf00Izzz^Vv5&S#{1yX0rb>)1cl&drM7>)Boun(dBP>+rqp
zimob#N^9DQdQRnQ97pH7x$E)ysbMRV8u-D9Ighay26fAx%F@)F4LA?Ybg2!eW+eg
z<;-Z-G#0<1YR26p+z|CzM1ESgdsgsWC{sf{XLTj@C1)pVt&VGr1(I~gwA$3w+Nn0U
zfl&&nu2xlD)hcS6#%X2o_v3~g#5q4v>niIP6{THKPSisF;Oa?6ly-K=uhKv)Nn7$J
zPJ4}Wx&+tgqW9G@`rq60sbtOSrJY*FIJwmiP5f%_hA8drk>3hKV%~2RzLA+>=Eqs$
zmVq8$_P*5ZD6s7)xxW?no3@yt{o>MQZJXJ>F_o*Cllva)h*Xl03ndXn49i)_)-zV9J<;!y-N=HZJsyWE2X{yzR!^k4X
z_rh=3?fF4}?!k@eyw5E&9_^!;@#ARf*)aPoN(nU4KlrnT<+gMAEP7-IA-ma`u&imd
zjg0j8hzNs+bJDG?%g7(>n{(?i%X1HJvLChL`MgkID=GdXuoo5xKmY;|fB*y_009U<
z00Izz00cfNfqk;sknWf6KPVlSzbuu?$6q`!9nXmz%Qbua%aG&4(&2HQwTl$r2<(Lg
z0uX=z1Rwwb2tWV=5P$##AOL}nP~i4vBloT^0pj2Pvp@RB0s#m>00Izz00bZa0SG_<
z0uX?}3JYNVzrx8y(;xr=2tWV=5P$##AOHafKmY=X0OtSb3J`z*1Rwwb2tWV=5P$##
zAOL~Y7r^{~^>d6CLI45~fB*y_009U<00Izz00c1qM<0Ly1Rwwb2tWV=5P$##AOHaf
ztiC|}|Nrs-|5iWGXdwh3009U<00Izz00bZa0SK(O0OtSeoqx0*0uX=z1Rwwb2tWV=
l5P$##)
+{
+ private const string SectionName = nameof(DbOptions);
+ private readonly IConfiguration _configuration = configuration;
+
+ public void Configure(DbOptions options) => _configuration.GetSection(SectionName).Bind(options);
+}
\ No newline at end of file
diff --git a/src/SanctionsSearch.Worker/Setup/OfacFileServiceOptionsSetup.cs b/src/SanctionsSearch.Worker/Setup/OfacFileServiceOptionsSetup.cs
new file mode 100644
index 0000000..3768606
--- /dev/null
+++ b/src/SanctionsSearch.Worker/Setup/OfacFileServiceOptionsSetup.cs
@@ -0,0 +1,9 @@
+namespace SanctionsSearch.Worker.Setup;
+
+class OfacFileServiceOptionsSetup(IConfiguration configuration) : IConfigureOptions
+{
+ private const string SectionName = nameof(OfacFileServiceOptions);
+ private readonly IConfiguration _configuration = configuration;
+
+ public void Configure(OfacFileServiceOptions options) => _configuration.GetSection(SectionName).Bind(options);
+}
\ No newline at end of file
diff --git a/src/SanctionsSearch.Worker/Usings.cs b/src/SanctionsSearch.Worker/Usings.cs
index 4adbc67..dc795a2 100644
--- a/src/SanctionsSearch.Worker/Usings.cs
+++ b/src/SanctionsSearch.Worker/Usings.cs
@@ -3,7 +3,10 @@ global using Microsoft.Extensions.Options;
global using SanctionsSearch.Worker.Interfaces;
global using SanctionsSearch.Worker.Options;
global using SanctionsSearch.Worker;
+global using SanctionsSearch.Worker.Models;
global using Serilog;
global using Serilog.Exceptions;
global using Serilog.Formatting.Compact;
+
+global using Microsoft.EntityFrameworkCore;
\ No newline at end of file
diff --git a/src/SanctionsSearch.Worker/appsettings.Example.json b/src/SanctionsSearch.Worker/appsettings.Example.json
index 3ddce01..5e8a9c5 100644
--- a/src/SanctionsSearch.Worker/appsettings.Example.json
+++ b/src/SanctionsSearch.Worker/appsettings.Example.json
@@ -15,5 +15,8 @@
"ConAddressesFileName": "CONS_ADD.CSV",
"ConAltNamesFileName": "CONS_ALT.CSV",
"ConCommentsFileName": "CONS_COMMENTS.CSV"
+ },
+ "DbOptions": {
+ "DatabaseName": "SanctionsSearch.example.db"
}
}
\ No newline at end of file