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