feat: work on implementing UoW pattern
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
namespace SanctionsSearch.Worker.Interfaces;
|
||||
|
||||
interface IRepository<T> where T : Entity
|
||||
{
|
||||
Task Upsert(T entity);
|
||||
Task<IEnumerable<T>> Find(Expression<Func<T, bool>> predicate);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
namespace SanctionsSearch.Worker.Interfaces;
|
||||
|
||||
interface ISdnRepository : IRepository<Sdn>
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace SanctionsSearch.Worker.Interfaces;
|
||||
|
||||
interface IUnitOfWork
|
||||
{
|
||||
ISdnRepository Sdns { get; }
|
||||
Task SaveChangesAsync();
|
||||
}
|
||||
Generated
+222
@@ -0,0 +1,222 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
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("20240821035135_update_models_with_timestamps")]
|
||||
partial class update_models_with_timestamps
|
||||
{
|
||||
/// <inheritdoc />
|
||||
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<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("CityProvincePostal")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Country")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Remarks")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("SdnId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("StreetAddress")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("SdnId");
|
||||
|
||||
b.ToTable("Addresses");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SanctionsSearch.Worker.Models.Alias", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Remarks")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("SdnId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Type")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("SdnId");
|
||||
|
||||
b.ToTable("Aliases");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SanctionsSearch.Worker.Models.Comment", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Remarks")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("SdnId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("SdnId");
|
||||
|
||||
b.ToTable("Comments");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SanctionsSearch.Worker.Models.Sdn", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("CallSign")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("GrossRegisteredTonnage")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Program")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Remarks")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Tonnage")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Type")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("VesselFlag")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("VesselOwner")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("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
|
||||
}
|
||||
}
|
||||
}
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace SanctionsSearch.Worker.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class update_models_with_timestamps : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
name: "CreatedAt",
|
||||
table: "Sdns",
|
||||
type: "TEXT",
|
||||
nullable: false,
|
||||
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
name: "UpdatedAt",
|
||||
table: "Sdns",
|
||||
type: "TEXT",
|
||||
nullable: false,
|
||||
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
name: "CreatedAt",
|
||||
table: "Comments",
|
||||
type: "TEXT",
|
||||
nullable: false,
|
||||
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
name: "UpdatedAt",
|
||||
table: "Comments",
|
||||
type: "TEXT",
|
||||
nullable: false,
|
||||
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
name: "CreatedAt",
|
||||
table: "Aliases",
|
||||
type: "TEXT",
|
||||
nullable: false,
|
||||
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
name: "UpdatedAt",
|
||||
table: "Aliases",
|
||||
type: "TEXT",
|
||||
nullable: false,
|
||||
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
name: "CreatedAt",
|
||||
table: "Addresses",
|
||||
type: "TEXT",
|
||||
nullable: false,
|
||||
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
name: "UpdatedAt",
|
||||
table: "Addresses",
|
||||
type: "TEXT",
|
||||
nullable: false,
|
||||
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "CreatedAt",
|
||||
table: "Sdns");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "UpdatedAt",
|
||||
table: "Sdns");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "CreatedAt",
|
||||
table: "Comments");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "UpdatedAt",
|
||||
table: "Comments");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "CreatedAt",
|
||||
table: "Aliases");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "UpdatedAt",
|
||||
table: "Aliases");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "CreatedAt",
|
||||
table: "Addresses");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "UpdatedAt",
|
||||
table: "Addresses");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
@@ -30,6 +31,9 @@ namespace SanctionsSearch.Worker.Migrations
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Remarks")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
@@ -41,6 +45,9 @@ namespace SanctionsSearch.Worker.Migrations
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("SdnId");
|
||||
@@ -54,6 +61,9 @@ namespace SanctionsSearch.Worker.Migrations
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
@@ -69,6 +79,9 @@ namespace SanctionsSearch.Worker.Migrations
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("SdnId");
|
||||
@@ -82,6 +95,9 @@ namespace SanctionsSearch.Worker.Migrations
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Remarks")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
@@ -89,6 +105,9 @@ namespace SanctionsSearch.Worker.Migrations
|
||||
b.Property<int>("SdnId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("SdnId");
|
||||
@@ -106,6 +125,9 @@ namespace SanctionsSearch.Worker.Migrations
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("GrossRegisteredTonnage")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
@@ -134,6 +156,9 @@ namespace SanctionsSearch.Worker.Migrations
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("VesselFlag")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
namespace SanctionsSearch.Worker.Models;
|
||||
|
||||
class Address
|
||||
class Address : Entity
|
||||
{
|
||||
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;
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
namespace SanctionsSearch.Worker.Models;
|
||||
|
||||
class Alias
|
||||
class Alias : Entity
|
||||
{
|
||||
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;
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
namespace SanctionsSearch.Worker.Models;
|
||||
|
||||
class Comment
|
||||
class Comment : Entity
|
||||
{
|
||||
public int SdnId { get; set; }
|
||||
public int Id { get; set; }
|
||||
public string Remarks { get; set; } = string.Empty;
|
||||
|
||||
public virtual Sdn Sdn { get; set; } = default!;
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace SanctionsSearch.Worker.Models;
|
||||
|
||||
abstract class Entity
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public DateTime UpdatedAt { get; set; }
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
namespace SanctionsSearch.Worker.Models;
|
||||
|
||||
class Sdn
|
||||
class Sdn : Entity
|
||||
{
|
||||
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;
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
using System.Reflection;
|
||||
|
||||
using Microsoft.Data.Sqlite;
|
||||
|
||||
namespace SanctionsSearch.Worker.Persistence;
|
||||
|
||||
class AppDbContext(IOptionsSnapshot<DbOptions> options) : DbContext, IDisposable
|
||||
class AppDbContext(DbOptions options) : DbContext
|
||||
{
|
||||
private readonly IOptionsSnapshot<DbOptions> _options = options;
|
||||
private readonly DbOptions _options = options;
|
||||
private SqliteConnection? _connection;
|
||||
internal string DatabasePath { get; private set; } = string.Empty;
|
||||
public DbSet<Sdn> Sdns { get; set; } = default!;
|
||||
public DbSet<Address> Addresses { get; set; } = default!;
|
||||
public DbSet<Alias> Aliases { get; set; } = default!;
|
||||
@@ -24,7 +21,8 @@ class AppDbContext(IOptionsSnapshot<DbOptions> options) : DbContext, IDisposable
|
||||
Directory.CreateDirectory(dataDir);
|
||||
}
|
||||
|
||||
var dbPath = Path.Combine(dataDir, _options.Value.DatabaseName);
|
||||
var dbPath = Path.Combine(dataDir, _options.DatabaseName);
|
||||
DatabasePath = dbPath;
|
||||
|
||||
_connection = new SqliteConnection($"Data Source={dbPath}");
|
||||
_connection.Open();
|
||||
@@ -32,9 +30,40 @@ class AppDbContext(IOptionsSnapshot<DbOptions> options) : DbContext, IDisposable
|
||||
optionsBuilder.UseSqlite(_connection);
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
public async override Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
_connection?.Dispose();
|
||||
base.Dispose();
|
||||
// TODO: Use TimeProvider instead of DateTime.UtcNow
|
||||
var now = DateTime.UtcNow;
|
||||
|
||||
foreach (var changedEntity in ChangeTracker.Entries())
|
||||
{
|
||||
if (changedEntity.Entity is Entity entity)
|
||||
{
|
||||
switch (changedEntity.State)
|
||||
{
|
||||
case EntityState.Added:
|
||||
entity.CreatedAt = now;
|
||||
entity.UpdatedAt = now;
|
||||
break;
|
||||
|
||||
case EntityState.Modified:
|
||||
Entry(entity).Property(x => x.CreatedAt).IsModified = false;
|
||||
entity.UpdatedAt = now;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return await base.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public async override ValueTask DisposeAsync()
|
||||
{
|
||||
if (_connection is not null)
|
||||
{
|
||||
await _connection.DisposeAsync();
|
||||
}
|
||||
|
||||
await base.DisposeAsync();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
namespace SanctionsSearch.Worker.Persistence;
|
||||
|
||||
class EfRepository<T> : IRepository<T> where T : Entity
|
||||
{
|
||||
protected readonly AppDbContext _context;
|
||||
protected readonly ILogger<EfRepository<T>> _logger;
|
||||
|
||||
public EfRepository(AppDbContext context, ILogger<EfRepository<T>> logger)
|
||||
{
|
||||
_context = context;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<T>> Find(Expression<Func<T, bool>> predicate)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await _context.Set<T>().Where(predicate).ToListAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error finding entities of type {Type}", typeof(T).Name);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Upsert(T entity)
|
||||
{
|
||||
try
|
||||
{
|
||||
var existing = await _context.Set<T>().FindAsync(entity.Id);
|
||||
|
||||
if (existing is null)
|
||||
{
|
||||
await _context.Set<T>().AddAsync(entity);
|
||||
return;
|
||||
}
|
||||
|
||||
_context.Entry(existing).CurrentValues.SetValues(entity);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error upserting entity of type {Type} with {Id}", typeof(T).Name, entity.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace SanctionsSearch.Worker.Persistence;
|
||||
|
||||
class EfUnitOfWork(AppDbContext context, ILoggerFactory loggerFactory) : IUnitOfWork, IAsyncDisposable
|
||||
{
|
||||
private readonly AppDbContext _context = context;
|
||||
public ISdnRepository Sdns { get; } = new SdnRepository(context, loggerFactory.CreateLogger<SdnRepository>());
|
||||
|
||||
public async Task SaveChangesAsync()
|
||||
{
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
await _context.DisposeAsync();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace SanctionsSearch.Worker.Persistence;
|
||||
|
||||
class SdnRepository(
|
||||
AppDbContext dbContext,
|
||||
ILogger<SdnRepository> logger
|
||||
) : EfRepository<Sdn>(dbContext, logger), ISdnRepository
|
||||
{
|
||||
}
|
||||
@@ -31,6 +31,7 @@ try
|
||||
|
||||
builder.Services.ConfigureOptions<OfacFileServiceOptionsSetup>();
|
||||
builder.Services.ConfigureOptions<DbOptionsSetup>();
|
||||
builder.Services.AddScoped(rs => rs.GetRequiredService<IOptionsSnapshot<DbOptions>>().Value);
|
||||
|
||||
builder.Services.AddDbContext<AppDbContext>();
|
||||
builder.Services.AddHostedService<Worker>();
|
||||
|
||||
@@ -9,4 +9,10 @@ global using Serilog;
|
||||
global using Serilog.Exceptions;
|
||||
global using Serilog.Formatting.Compact;
|
||||
|
||||
global using Microsoft.EntityFrameworkCore;
|
||||
global using Microsoft.EntityFrameworkCore;
|
||||
|
||||
global using System.Linq.Expressions;
|
||||
|
||||
global using System.Reflection;
|
||||
|
||||
global using Microsoft.Data.Sqlite;
|
||||
Reference in New Issue
Block a user