using System.Diagnostics.CodeAnalysis; using EntityFramework.Exceptions.PostgreSQL; using Hydra.Backend.Database.Models; using Hydra.Backend.Utils; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Design; using Microsoft.EntityFrameworkCore.Diagnostics; using Npgsql; namespace Hydra.Backend.Database; public class HydraContext : DbContext { private readonly NpgsqlDataSource _dataSource; private readonly ILoggerFactory? _loggerFactory; public DbSet Accounts { get; set; } public DbSet Members { get; set; } public DbSet Tokens { get; set; } public DbSet Applications { get; set; } public HydraContext(Config config, ILoggerFactory? loggerFactory) { var connString = new NpgsqlConnectionStringBuilder(config.Database.Url) { Timeout = config.Database.Timeout ?? 5, MaxPoolSize = config.Database.MaxPoolSize ?? 50, }.ConnectionString; var dataSourceBuilder = new NpgsqlDataSourceBuilder(connString); dataSourceBuilder.UseNodaTime(); _dataSource = dataSourceBuilder.Build(); _loggerFactory = loggerFactory; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) => optionsBuilder .ConfigureWarnings(c => c.Ignore(CoreEventId.ManyServiceProvidersCreatedWarning) .Ignore(CoreEventId.SaveChangesFailed)) .UseNpgsql(_dataSource, o => o.UseNodaTime()) .UseSnakeCaseNamingConvention() .UseLoggerFactory(_loggerFactory) .UseExceptionProcessor(); protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) { // ULIDs are stored as UUIDs in the database configurationBuilder.Properties().HaveConversion(); } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity().HasIndex(u => u.Name).IsUnique(); modelBuilder.Entity().HasIndex(m => new { m.AccountId, m.Name }).IsUnique(); } } [SuppressMessage("ReSharper", "UnusedType.Global", Justification = "Used when generating migrations")] public class DesignTimeDatabaseContextFactory : IDesignTimeDbContextFactory { public HydraContext CreateDbContext(string[] args) { // Read the configuration file var config = new ConfigurationBuilder() .AddConfiguration(args) .Build() // Get the configuration as our config class .Get() ?? new(); return new HydraContext(config, null); } }