2024-08-13 13:08:50 +02:00
|
|
|
using Catalogger.Backend.Database.Models;
|
|
|
|
|
using Catalogger.Backend.Extensions;
|
|
|
|
|
using EntityFramework.Exceptions.PostgreSQL;
|
|
|
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
|
using Microsoft.EntityFrameworkCore.ChangeTracking;
|
|
|
|
|
using Microsoft.EntityFrameworkCore.Design;
|
|
|
|
|
using Microsoft.EntityFrameworkCore.Diagnostics;
|
|
|
|
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
|
|
|
using Npgsql;
|
|
|
|
|
|
|
|
|
|
namespace Catalogger.Backend.Database;
|
|
|
|
|
|
|
|
|
|
public class DatabaseContext : DbContext
|
|
|
|
|
{
|
|
|
|
|
private readonly NpgsqlDataSource _dataSource;
|
|
|
|
|
private readonly ILoggerFactory? _loggerFactory;
|
|
|
|
|
|
|
|
|
|
public DbSet<Guild> Guilds { get; set; }
|
|
|
|
|
public DbSet<Message> Messages { get; set; }
|
|
|
|
|
public DbSet<IgnoredMessage> IgnoredMessages { get; set; }
|
|
|
|
|
public DbSet<Invite> Invites { get; set; }
|
|
|
|
|
public DbSet<Watchlist> Watchlists { get; set; }
|
|
|
|
|
|
|
|
|
|
public DatabaseContext(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);
|
2024-10-09 17:35:11 +02:00
|
|
|
dataSourceBuilder.EnableDynamicJson().UseNodaTime();
|
2024-08-13 13:08:50 +02:00
|
|
|
_dataSource = dataSourceBuilder.Build();
|
|
|
|
|
_loggerFactory = loggerFactory;
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-09 17:35:11 +02:00
|
|
|
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) =>
|
|
|
|
|
optionsBuilder
|
2024-08-13 13:08:50 +02:00
|
|
|
.ConfigureWarnings(c =>
|
|
|
|
|
c.Ignore(CoreEventId.ManyServiceProvidersCreatedWarning)
|
2024-10-09 17:35:11 +02:00
|
|
|
.Ignore(CoreEventId.SaveChangesFailed)
|
|
|
|
|
)
|
2024-08-13 13:08:50 +02:00
|
|
|
.UseNpgsql(_dataSource, o => o.UseNodaTime())
|
|
|
|
|
.UseSnakeCaseNamingConvention()
|
|
|
|
|
.UseLoggerFactory(_loggerFactory)
|
|
|
|
|
.UseExceptionProcessor();
|
|
|
|
|
|
|
|
|
|
protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
|
|
|
|
|
{
|
|
|
|
|
configurationBuilder.Properties<ulong>().HaveConversion<UlongValueConverter>();
|
|
|
|
|
configurationBuilder.Properties<List<ulong>>().HaveConversion<UlongArrayValueConverter>();
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-09 17:35:11 +02:00
|
|
|
private static readonly ValueComparer<List<ulong>> UlongListValueComparer =
|
|
|
|
|
new(
|
|
|
|
|
(c1, c2) => c1 != null && c2 != null && c1.SequenceEqual(c2),
|
|
|
|
|
c => c.Aggregate(0, (a, v) => HashCode.Combine(a, v.GetHashCode()))
|
|
|
|
|
);
|
2024-08-13 13:08:50 +02:00
|
|
|
|
|
|
|
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
|
|
|
|
{
|
2024-10-09 17:35:11 +02:00
|
|
|
modelBuilder
|
|
|
|
|
.Entity<Guild>()
|
|
|
|
|
.Property(g => g.KeyRoles)
|
2024-08-13 13:08:50 +02:00
|
|
|
.Metadata.SetValueComparer(UlongListValueComparer);
|
|
|
|
|
|
|
|
|
|
modelBuilder.Entity<Invite>().HasKey(i => i.Code);
|
|
|
|
|
modelBuilder.Entity<Invite>().HasIndex(i => i.GuildId);
|
|
|
|
|
|
|
|
|
|
modelBuilder.Entity<Watchlist>().HasKey(w => new { w.GuildId, w.UserId });
|
|
|
|
|
modelBuilder.Entity<Watchlist>().Property(w => w.AddedAt).HasDefaultValueSql("now()");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class DesignTimeDatabaseContextFactory : IDesignTimeDbContextFactory<DatabaseContext>
|
|
|
|
|
{
|
|
|
|
|
public DatabaseContext CreateDbContext(string[] args)
|
|
|
|
|
{
|
|
|
|
|
// Read the configuration file
|
2024-10-09 17:35:11 +02:00
|
|
|
var config =
|
|
|
|
|
new ConfigurationBuilder()
|
|
|
|
|
.AddConfiguration()
|
|
|
|
|
.Build()
|
|
|
|
|
// Get the configuration as our config class
|
|
|
|
|
.Get<Config>() ?? new();
|
2024-08-13 13:08:50 +02:00
|
|
|
|
|
|
|
|
return new DatabaseContext(config, null);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-09 17:35:11 +02:00
|
|
|
public class UlongValueConverter()
|
|
|
|
|
: ValueConverter<ulong, long>(
|
|
|
|
|
convertToProviderExpression: x => (long)x,
|
|
|
|
|
convertFromProviderExpression: x => (ulong)x
|
|
|
|
|
);
|
2024-08-13 13:08:50 +02:00
|
|
|
|
2024-10-09 17:35:11 +02:00
|
|
|
public class UlongArrayValueConverter()
|
|
|
|
|
: ValueConverter<List<ulong>, List<long>>(
|
|
|
|
|
convertToProviderExpression: x => x.Select(i => (long)i).ToList(),
|
|
|
|
|
convertFromProviderExpression: x => x.Select(i => (ulong)i).ToList()
|
|
|
|
|
);
|