using MaBibli.Shared.Entites; using Microsoft.EntityFrameworkCore; namespace MaBibli.Api.Data; public class MaBibliDbContext(DbContextOptions options) : DbContext(options) { public DbSet Livres => Set(); public DbSet Auteurs => Set(); public DbSet LivreAuteurs => Set(); public DbSet StatutsLecture => Set(); public DbSet RapprochementsRefuses => Set(); public DbSet Prets => Set(); protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity(livre => { livre.Property(l => l.Titre).IsRequired(); livre.Property(l => l.TitreNormalise).IsRequired(); livre.HasIndex(l => l.Isbn); // Le tri et la recherche passent par là : sans index, chaque frappe balaie la table. livre.HasIndex(l => l.TitreNormalise); livre.HasMany(l => l.Prets) .WithOne(p => p.Livre) .HasForeignKey(p => p.LivreId) .OnDelete(DeleteBehavior.Cascade); }); modelBuilder.Entity(auteur => { auteur.Property(a => a.Nom).IsRequired(); auteur.Property(a => a.NomNormalise).IsRequired(); auteur.Property(a => a.CleRegroupement).IsRequired(); // Unicité de la clé de regroupement : « Zola, Émile » et « Émile Zola » produisent // la même clé et ne peuvent donc pas coexister. C'est la garantie structurelle du // regroupement — le code applicatif peut avoir un trou, la base non. auteur.HasIndex(a => a.CleRegroupement).IsUnique(); auteur.HasIndex(a => a.NomNormalise); }); modelBuilder.Entity(lien => { lien.HasKey(la => new { la.LivreId, la.AuteurId }); lien.HasOne(la => la.Livre) .WithMany(l => l.Auteurs) .HasForeignKey(la => la.LivreId) .OnDelete(DeleteBehavior.Cascade); // Restrict : supprimer un auteur encore rattaché à des livres les priverait de leur // auteur en silence. On passe par une fusion, ou par la suppression des livres. lien.HasOne(la => la.Auteur) .WithMany(a => a.Livres) .HasForeignKey(la => la.AuteurId) .OnDelete(DeleteBehavior.Restrict); lien.HasIndex(la => la.AuteurId); }); modelBuilder.Entity(statut => { statut.Property(s => s.Utilisateur).IsRequired(); statut.HasOne(s => s.Livre) .WithMany(l => l.Statuts) .HasForeignKey(s => s.LivreId) .OnDelete(DeleteBehavior.Cascade); // Une personne, un statut par livre. L'unicité est ce qui rend l'écriture idempotente : // on lit la ligne, on la met à jour, et il ne peut jamais y en avoir deux à départager. statut.HasIndex(s => new { s.LivreId, s.Utilisateur }).IsUnique(); statut.HasIndex(s => s.Utilisateur); }); modelBuilder.Entity(refus => { // Le couple est rangé (petit identifiant d'abord) à l'écriture : l'unicité vaut donc // dans les deux sens, et un refus ne peut pas être enregistré deux fois. refus.HasIndex(r => new { r.AuteurAId, r.AuteurBId }).IsUnique(); }); modelBuilder.Entity(pret => { pret.Property(p => p.Emprunteur).IsRequired(); pret.HasIndex(p => p.LivreId); }); } }