using Microsoft.EntityFrameworkCore; namespace SQLInsight.Hub.Data; public sealed class HubDbContext(DbContextOptions options) : DbContext(options) { public DbSet Customers => Set(); public DbSet Licenses => Set(); public DbSet Instances => Set(); public DbSet Submissions => Set(); public DbSet Findings => Set(); public DbSet RuleStates => Set(); public DbSet SupportCases => Set(); public DbSet StaffUsers => Set(); public DbSet VersionChanges => Set(); protected override void OnModelCreating(ModelBuilder modelBuilder) { ArgumentNullException.ThrowIfNull(modelBuilder); modelBuilder.Entity(e => { e.HasIndex(c => c.Name).IsUnique(); }); modelBuilder.Entity(e => { e.HasKey(l => l.LicenseId); e.HasOne(l => l.Customer).WithMany(c => c.Licenses).HasForeignKey(l => l.CustomerId); }); modelBuilder.Entity(e => { e.HasIndex(i => new { i.CustomerId, i.InstanceKey }).IsUnique(); e.HasOne(i => i.Customer).WithMany(c => c.Instances).HasForeignKey(i => i.CustomerId); }); modelBuilder.Entity(e => { e.HasKey(s => s.SubmissionId); e.HasIndex(s => s.ReceivedAt); }); modelBuilder.Entity(e => { e.HasOne(f => f.Instance).WithMany(i => i.Findings).HasForeignKey(f => f.InstanceId); e.Property(f => f.EvidenceJson).HasColumnType("jsonb"); // One active occurrence per instance, rule and subject; history keeps resolved ones. e.HasIndex(f => new { f.InstanceId, f.RuleId, f.Subject }).IsUnique().HasFilter("resolved_at IS NULL"); e.HasIndex(f => new { f.Severity, f.ResolvedAt }); e.HasOne(f => f.SupportCase).WithMany(c => c.Findings).HasForeignKey(f => f.SupportCaseId).OnDelete(DeleteBehavior.SetNull); }); modelBuilder.Entity(e => { e.HasKey(r => new { r.InstanceId, r.RuleId }); }); modelBuilder.Entity(e => { e.HasOne(c => c.Customer).WithMany(c => c.SupportCases).HasForeignKey(c => c.CustomerId); }); modelBuilder.Entity(e => { e.HasOne(v => v.Instance).WithMany().HasForeignKey(v => v.InstanceId); e.HasIndex(v => new { v.InstanceId, v.ChangedAt }); }); modelBuilder.Entity(e => { e.HasIndex(u => u.UserName).IsUnique(); }); } }