using EARSystem.Core; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Design; namespace EARSystem.Infrastructure; public class ApplicationUser : IdentityUser { public string DisplayName { get; set; } = ""; public bool IsDemo { get; set; } } public class AppDbContext(DbContextOptions options) : IdentityDbContext(options) { public DbSet Moods => Set(); public DbSet Preferences => Set(); public DbSet Places => Set(); public DbSet Atmospheres => Set(); public DbSet Experiences => Set(); public DbSet Favorites => Set(); public DbSet Recommendations => Set(); public DbSet Rules => Set(); protected override void OnModelCreating(ModelBuilder model) { base.OnModelCreating(model); model.Entity().Property(x => x.DisplayName).HasMaxLength(40); model.Entity(b => { b.HasIndex(x => new { x.UserId, x.RecordedAt }); b.Property(x => x.Thoughts).HasMaxLength(5000); b.Property(x => x.TagsJson).HasMaxLength(1000); b.Property(x => x.Version).IsConcurrencyToken(); b.HasOne().WithMany().HasForeignKey(x => x.UserId).OnDelete(DeleteBehavior.Cascade); }); model.Entity(b => { b.HasKey(x => x.UserId); b.Property(x => x.Budget).HasPrecision(10, 2); b.HasOne().WithOne().HasForeignKey(x => x.UserId).OnDelete(DeleteBehavior.Cascade); }); model.Entity(b => { b.Property(x => x.Name).HasMaxLength(100); b.Property(x => x.Address).HasMaxLength(300); b.Property(x => x.Description).HasMaxLength(1000); b.Property(x => x.AuthorizedExternalId).HasMaxLength(100); b.Property(x => x.Price).HasPrecision(10, 2); b.HasIndex(x => new { x.Source, x.Category }); b.HasOne(x => x.Atmosphere).WithOne().HasForeignKey(x => x.PlaceId).OnDelete(DeleteBehavior.Cascade); }); model.Entity().HasKey(x => x.PlaceId); model.Entity().Property(x => x.Evidence).HasMaxLength(500); model.Entity(b => { b.HasIndex(x => new { x.UserId, x.PlaceId, x.VisitDay }).IsUnique(); b.HasIndex(x => new { x.UserId, x.VisitedAt }); b.HasIndex(x => new { x.PlaceId, x.Contribute }); b.Property(x => x.Thoughts).HasMaxLength(5000); b.Property(x => x.Version).IsConcurrencyToken(); b.HasOne(x => x.Place).WithMany().HasForeignKey(x => x.PlaceId).OnDelete(DeleteBehavior.Restrict); b.HasOne().WithMany().HasForeignKey(x => x.UserId).OnDelete(DeleteBehavior.Cascade); }); model.Entity(b => { b.HasKey(x => new { x.UserId, x.PlaceId }); b.HasOne(x => x.Place).WithMany().HasForeignKey(x => x.PlaceId).OnDelete(DeleteBehavior.Restrict); b.HasOne().WithMany().HasForeignKey(x => x.UserId).OnDelete(DeleteBehavior.Cascade); }); model.Entity(b => { b.HasIndex(x => new { x.UserId, x.CreatedAt }); b.Property(x => x.AlgorithmVersion).HasMaxLength(50); b.HasOne().WithMany().HasForeignKey(x => x.UserId).OnDelete(DeleteBehavior.Cascade); }); model.Entity(b => { b.Property(x => x.Version).HasMaxLength(50); b.Property(x => x.ConcurrencyStamp).IsConcurrencyToken(); }); // UTC ticks preserve ordering on both SQL Server and the isolated SQLite test database. foreach (var type in model.Model.GetEntityTypes()) foreach (var property in type.GetProperties().Where(p => p.ClrType == typeof(DateTimeOffset))) property.SetValueConverter(new Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter( value => value.UtcTicks, ticks => new DateTimeOffset(ticks, TimeSpan.Zero))); } } public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory { public AppDbContext CreateDbContext(string[] args) { var connection = Environment.GetEnvironmentVariable("ConnectionStrings__DefaultConnection") ?? "Server=(localdb)\\MSSQLLocalDB;Database=EARSystem;Trusted_Connection=True;TrustServerCertificate=True"; return new(new DbContextOptionsBuilder().UseSqlServer(connection).Options); } }