using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace Wave.Data; public class ApplicationDbContext(DbContextOptions options) : IdentityDbContext(options) { protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); var dateTimeOffsetUtcConverter = new ValueConverter( model => model.ToUniversalTime(), utc => utc.ToLocalTime() ); builder.Entity(user => { user.Property(u => u.FullName).HasMaxLength(64); user.Property(u => u.AboutTheAuthor).HasMaxLength(512); user.Property(u => u.Biography).HasMaxLength(4096); user.HasOne(u => u.ProfilePicture).WithOne().HasForeignKey(typeof(ProfilePicture)) .OnDelete(DeleteBehavior.SetNull); user.HasMany(u => u.Links).WithOne().OnDelete(DeleteBehavior.Cascade); user.Navigation(u => u.ProfilePicture).IsRequired(false); user.Navigation(u => u.Links).AutoInclude(); }); builder.Entity(pfp => { pfp.HasKey(p => p.Id); pfp.Property(p => p.ImageId).IsRequired(); pfp.ToTable("ProfilePictures"); }); builder.Entity
(article => { article.HasKey(a => a.Id); article.Property(a => a.Title) .IsRequired().HasMaxLength(256); article.HasOne(a => a.Author).WithMany(a => a.Articles) .IsRequired().OnDelete(DeleteBehavior.Cascade); article.HasOne(a => a.Reviewer).WithMany() .IsRequired(false).OnDelete(DeleteBehavior.SetNull); article.Property(a => a.CreationDate) .IsRequired().HasDefaultValueSql("now()") .HasConversion(dateTimeOffsetUtcConverter); article.Property(a => a.PublishDate) .HasConversion(dateTimeOffsetUtcConverter); article.Property(a => a.LastModified) .IsRequired().HasDefaultValueSql("now()") .HasConversion(dateTimeOffsetUtcConverter); article.HasQueryFilter(a => !a.IsDeleted && a.Status >= ArticleStatus.Published && a.PublishDate <= DateTimeOffset.UtcNow); article.ToTable("Articles"); }); builder.HasCollation("default-case-insensitive", "und-u-kf-upper-ks-level1", "icu", false); builder.Entity(category => { category.HasKey(c => c.Id); category.Property(c => c.Name).IsRequired().HasMaxLength(128).UseCollation("default-case-insensitive"); category.HasIndex(c => c.Name).IsUnique(); category.Property(c => c.Color).IsRequired().HasSentinel(CategoryColors.Default) .HasDefaultValue(CategoryColors.Default); category.HasMany(c => c.Articles).WithMany(a => a.Categories) .UsingEntity( ac => ac.HasOne(a => a.Article).WithMany().OnDelete(DeleteBehavior.NoAction), ac => ac.HasOne(a => a.Category).WithMany().OnDelete(DeleteBehavior.NoAction), articleCategory => { articleCategory.HasKey(ac => ac.Id); articleCategory.ToTable("ArticleCategories"); articleCategory.HasQueryFilter(ac => !ac.Article.IsDeleted); }); category.ToTable("Categories"); }); builder.Entity(img => { img.HasKey(i => i.Id); img.Property(i => i.ImageDescription).IsRequired().HasMaxLength(2048); img.HasOne
().WithMany(a => a.Images).OnDelete(DeleteBehavior.Cascade); img.ToTable("Images"); }); builder.Entity(newsletter => { newsletter.HasKey(n => n.Id); newsletter.HasOne(n => n.Article).WithOne().HasForeignKey() .IsRequired().OnDelete(DeleteBehavior.Cascade); newsletter.Property(a => a.DistributionDateTime) .HasConversion(dateTimeOffsetUtcConverter); newsletter.ToTable("Newsletter"); }); builder.Entity(subscriber => { subscriber.HasKey(s => s.Id); subscriber.Property(s => s.Name).IsRequired(false).HasMaxLength(128); subscriber.Property(s => s.Email).IsRequired().HasMaxLength(256).UseCollation("default-case-insensitive"); subscriber.HasIndex(s => s.Email).IsUnique(); subscriber.HasIndex(s => s.Unsubscribed); subscriber.HasQueryFilter(s => !s.Unsubscribed); subscriber.ToTable("NewsletterSubscribers"); }); } }