feat(server): add database context and migrations
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
using GroundsForSupport.Server.Payments;
|
||||
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace GroundsForSupport.Server.Data;
|
||||
|
||||
internal sealed class Context(
|
||||
IOptions<ContextOptions> ctxOptions,
|
||||
DbContextOptions<Context> options
|
||||
) : DbContext(options)
|
||||
{
|
||||
private const string DataSourceKey = "Data Source=";
|
||||
private readonly ContextOptions _ctxOptions = ctxOptions.Value;
|
||||
|
||||
public DbSet<Payment> Payments => Set<Payment>();
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
{
|
||||
var dbPath = _ctxOptions.GetFullyQualifiedDatabasePath();
|
||||
var dbDirectory = Path.GetDirectoryName(dbPath) ?? throw new InvalidOperationException("Database directory path could not be determined.");
|
||||
|
||||
if (Directory.Exists(dbDirectory) is false)
|
||||
{
|
||||
Directory.CreateDirectory(dbDirectory);
|
||||
}
|
||||
|
||||
var connectionString = $"{DataSourceKey}{dbPath}";
|
||||
|
||||
optionsBuilder.UseSqlite(connectionString);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace GroundsForSupport.Server.Data;
|
||||
|
||||
internal sealed record ContextOptions
|
||||
{
|
||||
public string DatabaseFilePath { get; init; } = string.Empty;
|
||||
public string GetFullyQualifiedDatabasePath()
|
||||
{
|
||||
return Path.GetFullPath(DatabaseFilePath, AppContext.BaseDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed record ContextOptionsSetup : IConfigureOptions<ContextOptions>
|
||||
{
|
||||
private const string SectionName = nameof(ContextOptions);
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public ContextOptionsSetup(IConfiguration configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
public void Configure(ContextOptions options)
|
||||
{
|
||||
_configuration.GetSection(SectionName).Bind(options);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace GroundsForSupport.Server.Data;
|
||||
|
||||
internal sealed class MigrationService(
|
||||
IServiceProvider serviceProvider,
|
||||
ILogger<MigrationService> logger
|
||||
) : IHostedService
|
||||
{
|
||||
private readonly IServiceProvider _serviceProvider = serviceProvider;
|
||||
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
logger.LogInformation("Applying database migrations...");
|
||||
|
||||
using var scope = _serviceProvider.CreateScope();
|
||||
var context = scope.ServiceProvider.GetRequiredService<Context>();
|
||||
await context.Database.MigrateAsync(cancellationToken);
|
||||
|
||||
logger.LogInformation("Database migrations applied.");
|
||||
}
|
||||
|
||||
public Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user