using Microsoft.EntityFrameworkCore; namespace MeetingAssistant.Speakers; public sealed class SpeakerIdentity { public int Id { get; set; } public string? CanonicalName { get; set; } public int TranscriptionCount { get; set; } public DateTimeOffset CreatedAt { get; set; } public DateTimeOffset UpdatedAt { get; set; } public List CandidateNames { get; set; } = []; public List Aliases { get; set; } = []; public List Snippets { get; set; } = []; public string? GetDisplayName() { if (!string.IsNullOrWhiteSpace(CanonicalName)) { return CanonicalName; } return Aliases .Select(alias => alias.Name) .Where(alias => !string.IsNullOrWhiteSpace(alias)) .Order(StringComparer.OrdinalIgnoreCase) .FirstOrDefault(); } } public sealed class SpeakerCandidateName { public int Id { get; set; } public int SpeakerIdentityId { get; set; } public SpeakerIdentity? SpeakerIdentity { get; set; } public string Name { get; set; } = ""; } public sealed class SpeakerSnippet { public int Id { get; set; } public int SpeakerIdentityId { get; set; } public SpeakerIdentity? SpeakerIdentity { get; set; } public byte[] WavBytes { get; set; } = []; public DateTimeOffset CreatedAt { get; set; } } public sealed class SpeakerAlias { public int Id { get; set; } public int SpeakerIdentityId { get; set; } public SpeakerIdentity? SpeakerIdentity { get; set; } public string Name { get; set; } = ""; } public sealed class SpeakerIdentityDbContext : DbContext { public SpeakerIdentityDbContext(DbContextOptions options) : base(options) { } public DbSet SpeakerIdentities => Set(); public DbSet SpeakerCandidateNames => Set(); public DbSet SpeakerAliases => Set(); public DbSet SpeakerSnippets => Set(); protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity(entity => { entity.HasMany(identity => identity.CandidateNames) .WithOne(candidate => candidate.SpeakerIdentity) .HasForeignKey(candidate => candidate.SpeakerIdentityId) .OnDelete(DeleteBehavior.Cascade); entity.HasMany(identity => identity.Aliases) .WithOne(alias => alias.SpeakerIdentity) .HasForeignKey(alias => alias.SpeakerIdentityId) .OnDelete(DeleteBehavior.Cascade); entity.HasMany(identity => identity.Snippets) .WithOne(snippet => snippet.SpeakerIdentity) .HasForeignKey(snippet => snippet.SpeakerIdentityId) .OnDelete(DeleteBehavior.Cascade); }); modelBuilder.Entity() .HasIndex(candidate => new { candidate.SpeakerIdentityId, candidate.Name }) .IsUnique(); modelBuilder.Entity() .HasIndex(alias => new { alias.SpeakerIdentityId, alias.Name }) .IsUnique(); } }