using Foxchat.Chat.Database.Models; using Foxchat.Core; using Foxchat.Core.Database; using Foxchat.Core.Extensions; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Design; using Npgsql; namespace Foxchat.Chat.Database; public class ChatContext : IDatabaseContext { private readonly NpgsqlDataSource _dataSource; private readonly ILoggerFactory? _loggerFactory; public override DbSet Instance { get; set; } public DbSet IdentityInstances { get; set; } public DbSet Users { get; set; } public DbSet Guilds { get; set; } public DbSet Channels { get; set; } public DbSet Messages { get; set; } public ChatContext(InstanceConfig 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 .UseNpgsql(_dataSource, o => o.UseNodaTime()) .UseSnakeCaseNamingConvention() .UseLoggerFactory(_loggerFactory); 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(i => i.Domain).IsUnique(); modelBuilder.Entity().HasIndex(u => new { u.RemoteUserId, u.InstanceId }).IsUnique(); modelBuilder.Entity().HasIndex(u => new { u.Username, u.InstanceId }).IsUnique(); modelBuilder.Entity() .HasOne(e => e.Owner) .WithMany(e => e.OwnedGuilds) .HasForeignKey(e => e.OwnerId) .IsRequired(); modelBuilder.Entity() .HasMany(e => e.Guilds) .WithMany(e => e.Users); } } // ReSharper disable once UnusedType.Global public class DesignTimeIdentityContextFactory : IDesignTimeDbContextFactory { public ChatContext CreateDbContext(string[] args) { // Read the configuration file var config = new ConfigurationBuilder() .AddConfiguration("chat.ini") .Build() // Get the configuration as our config class .Get() ?? new(); return new ChatContext(config, null); } }