// Auto-generated by create-backlist — DO NOT EDIT MANUALLY using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.ChangeTracking; using <%= projectName %>.Models; namespace <%= projectName %>.Data { /// /// Main EF Core DbContext for <%= projectName %>. /// Includes: soft-delete global filter, automatic audit timestamps, /// unique indexes, and seed-data scaffolding hooks. /// public class ApplicationDbContext : DbContext { public ApplicationDbContext(DbContextOptions options) : base(options) { } // ── DbSets ──────────────────────────────────────────────────────────── <% modelsToGenerate.forEach(model => { %> /// Represents the <%= model.name %> table. public DbSet<<%= model.name %>> <%= model.name %>s { get; set; } <% }); %> // ── Model Configuration ─────────────────────────────────────────────── protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); <% modelsToGenerate.forEach(model => { %> // ── <%= model.name %> ────────────────────────────────────────────── modelBuilder.Entity<<%= model.name %>>(entity => { entity.HasKey(e => e.Id); // Soft-delete: only return rows where DeletedAt is null entity.HasQueryFilter(e => e.DeletedAt == null); // Unique indexes <% (model.fields || []).forEach(field => { if (field.isUnique) { %> entity.HasIndex(e => e.<%= field.name.charAt(0).toUpperCase() + field.name.slice(1) %>) .IsUnique() .HasDatabaseName("IX_<%= model.name %>_<%= field.name.charAt(0).toUpperCase() + field.name.slice(1) %>"); <% } }); %> // Column precision for decimal fields <% (model.fields || []).forEach(field => { const n = String(field.name || '').toLowerCase(); const isDecimal = field.type === 'Number' && (n.includes('price') || n.includes('amount') || n.includes('total') || n.includes('cost')); if (isDecimal) { %> entity.Property(e => e.<%= field.name.charAt(0).toUpperCase() + field.name.slice(1) %>) .HasColumnType("decimal(18,2)"); <% } }); %> // Audit timestamp defaults entity.Property(e => e.CreatedAt).HasDefaultValueSql("NOW()"); entity.Property(e => e.UpdatedAt).HasDefaultValueSql("NOW()"); // Table name override (snake_case convention) entity.ToTable("<%= model.name.replace(/([A-Z])/g, '_$1').toLowerCase().replace(/^_/, '') %>s"); }); <% }); %> } // ── Automatic Audit: SaveChanges / SaveChangesAsync ─────────────────── public override int SaveChanges(bool acceptAllChangesOnSuccess) { ApplyAuditInfo(); return base.SaveChanges(acceptAllChangesOnSuccess); } public override Task SaveChangesAsync( bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default) { ApplyAuditInfo(); return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken); } private void ApplyAuditInfo() { var now = DateTime.UtcNow; foreach (EntityEntry entry in ChangeTracker.Entries()) { if (entry.State == EntityState.Added) { if (entry.Properties.Any(p => p.Metadata.Name == "CreatedAt")) entry.Property("CreatedAt").CurrentValue = now; if (entry.Properties.Any(p => p.Metadata.Name == "UpdatedAt")) entry.Property("UpdatedAt").CurrentValue = now; } else if (entry.State == EntityState.Modified) { if (entry.Properties.Any(p => p.Metadata.Name == "UpdatedAt")) entry.Property("UpdatedAt").CurrentValue = now; // Prevent CreatedAt from being overwritten on update if (entry.Properties.Any(p => p.Metadata.Name == "CreatedAt")) entry.Property("CreatedAt").IsModified = false; } } } } }