after refactor cleanup
This commit is contained in:
199
DiunaBI.Infrastructure/Data/AppDbContext.cs
Normal file
199
DiunaBI.Infrastructure/Data/AppDbContext.cs
Normal file
@@ -0,0 +1,199 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using DiunaBI.Domain.Entities;
|
||||
|
||||
namespace DiunaBI.Infrastructure.Data;
|
||||
|
||||
public class AppDbContext(DbContextOptions<AppDbContext> options) : DbContext(options)
|
||||
{
|
||||
public DbSet<User> Users { get; init; }
|
||||
public DbSet<Layer> Layers { get; init; }
|
||||
public DbSet<Record> Records { get; init; }
|
||||
public DbSet<ProcessSource> ProcessSources { get; init; }
|
||||
public DbSet<DataInbox> DataInbox { get; init; }
|
||||
public DbSet<QueueJob> QueueJobs { get; init; }
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.Entity<User>().HasKey(x => x.Id);
|
||||
modelBuilder.Entity<User>().Property(x => x.Email).HasMaxLength(50);
|
||||
modelBuilder.Entity<User>().Property(x => x.UserName).HasMaxLength(50);
|
||||
|
||||
modelBuilder.Entity<Layer>().HasKey(x => x.Id);
|
||||
modelBuilder.Entity<Layer>().Property(x => x.Number).IsRequired();
|
||||
modelBuilder.Entity<Layer>().Property(x => x.Name).IsRequired().HasMaxLength(50);
|
||||
modelBuilder.Entity<Layer>().Property(x => x.Type).IsRequired().HasConversion<int>();
|
||||
modelBuilder.Entity<Layer>().Property(x => x.CreatedAt).IsRequired();
|
||||
modelBuilder.Entity<Layer>().Property(x => x.ModifiedAt).IsRequired();
|
||||
modelBuilder.Entity<Layer>().Property(x => x.IsDeleted).IsRequired().HasDefaultValue(false);
|
||||
modelBuilder.Entity<Layer>().Property(x => x.IsCancelled).IsRequired().HasDefaultValue(false);
|
||||
modelBuilder.Entity<Layer>().Property(x => x.CreatedById).IsRequired();
|
||||
modelBuilder.Entity<Layer>().Property(x => x.ModifiedById).IsRequired();
|
||||
|
||||
modelBuilder.Entity<Layer>()
|
||||
.HasOne(x => x.CreatedBy)
|
||||
.WithMany()
|
||||
.HasForeignKey(x => x.CreatedById)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
modelBuilder.Entity<Layer>()
|
||||
.HasOne(x => x.ModifiedBy)
|
||||
.WithMany()
|
||||
.HasForeignKey(x => x.ModifiedById)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
modelBuilder.Entity<Layer>()
|
||||
.HasMany(x => x.Records)
|
||||
.WithOne()
|
||||
.HasForeignKey(r => r.LayerId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<Record>().HasKey(x => x.Id);
|
||||
modelBuilder.Entity<Record>().Property(x => x.Code).IsRequired().HasMaxLength(50);
|
||||
modelBuilder.Entity<Record>().Property(x => x.Desc1).HasMaxLength(10000);
|
||||
modelBuilder.Entity<Record>().Property(x => x.CreatedAt);
|
||||
modelBuilder.Entity<Record>().Property(x => x.ModifiedAt);
|
||||
modelBuilder.Entity<Record>().Property(x => x.IsDeleted);
|
||||
modelBuilder.Entity<Record>().Property(x => x.CreatedById).IsRequired();
|
||||
modelBuilder.Entity<Record>().Property(x => x.ModifiedById).IsRequired();
|
||||
modelBuilder.Entity<Record>().Property(x => x.LayerId).IsRequired();
|
||||
|
||||
modelBuilder.Entity<Record>()
|
||||
.HasOne(x => x.CreatedBy)
|
||||
.WithMany()
|
||||
.HasForeignKey(x => x.CreatedById)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
modelBuilder.Entity<Record>()
|
||||
.HasOne(x => x.ModifiedBy)
|
||||
.WithMany()
|
||||
.HasForeignKey(x => x.ModifiedById)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
modelBuilder.Entity<Record>()
|
||||
.HasOne<Layer>()
|
||||
.WithMany(l => l.Records!)
|
||||
.HasForeignKey(x => x.LayerId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<ProcessSource>().HasKey(x => new { x.LayerId, x.SourceId });
|
||||
modelBuilder.Entity<ProcessSource>().Property(x => x.LayerId).IsRequired();
|
||||
modelBuilder.Entity<ProcessSource>().Property(x => x.SourceId).IsRequired();
|
||||
|
||||
modelBuilder.Entity<ProcessSource>()
|
||||
.HasOne<Layer>()
|
||||
.WithMany()
|
||||
.HasForeignKey(x => x.LayerId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<ProcessSource>()
|
||||
.HasOne(x => x.Source)
|
||||
.WithMany()
|
||||
.HasForeignKey(x => x.SourceId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
modelBuilder.Entity<DataInbox>().HasKey(x => x.Id);
|
||||
modelBuilder.Entity<DataInbox>().Property(x => x.Name).IsRequired().HasMaxLength(50);
|
||||
modelBuilder.Entity<DataInbox>().Property(x => x.Source).IsRequired().HasMaxLength(50);
|
||||
modelBuilder.Entity<DataInbox>().Property(x => x.Data).IsRequired();
|
||||
modelBuilder.Entity<DataInbox>().Property(x => x.CreatedAt);
|
||||
|
||||
modelBuilder.Entity<QueueJob>().HasKey(x => x.Id);
|
||||
modelBuilder.Entity<QueueJob>().Property(x => x.LayerId).IsRequired();
|
||||
modelBuilder.Entity<QueueJob>().Property(x => x.LayerName).IsRequired().HasMaxLength(200);
|
||||
modelBuilder.Entity<QueueJob>().Property(x => x.PluginName).IsRequired().HasMaxLength(100);
|
||||
modelBuilder.Entity<QueueJob>().Property(x => x.JobType).IsRequired().HasConversion<int>();
|
||||
modelBuilder.Entity<QueueJob>().Property(x => x.Priority);
|
||||
modelBuilder.Entity<QueueJob>().Property(x => x.CreatedAt).IsRequired();
|
||||
modelBuilder.Entity<QueueJob>().Property(x => x.RetryCount);
|
||||
modelBuilder.Entity<QueueJob>().Property(x => x.MaxRetries);
|
||||
modelBuilder.Entity<QueueJob>().Property(x => x.Status).IsRequired().HasConversion<int>();
|
||||
modelBuilder.Entity<QueueJob>().Property(x => x.LastError).HasMaxLength(1000);
|
||||
modelBuilder.Entity<QueueJob>().Property(x => x.LastAttemptAt);
|
||||
modelBuilder.Entity<QueueJob>().Property(x => x.CompletedAt);
|
||||
modelBuilder.Entity<QueueJob>().Property(x => x.CreatedById).IsRequired();
|
||||
modelBuilder.Entity<QueueJob>().Property(x => x.CreatedAtUtc).IsRequired();
|
||||
modelBuilder.Entity<QueueJob>().Property(x => x.ModifiedById).IsRequired();
|
||||
modelBuilder.Entity<QueueJob>().Property(x => x.ModifiedAtUtc).IsRequired();
|
||||
|
||||
// Configure automatic timestamps for entities with CreatedAt/ModifiedAt
|
||||
ConfigureTimestamps(modelBuilder);
|
||||
}
|
||||
|
||||
private void ConfigureTimestamps(ModelBuilder modelBuilder)
|
||||
{
|
||||
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
|
||||
{
|
||||
// Check if entity has CreatedAt property
|
||||
var createdAtProperty = entityType.FindProperty("CreatedAt");
|
||||
if (createdAtProperty != null)
|
||||
{
|
||||
modelBuilder.Entity(entityType.ClrType)
|
||||
.Property("CreatedAt")
|
||||
.HasDefaultValueSql("GETUTCDATE()");
|
||||
}
|
||||
|
||||
// Check if entity has ModifiedAt property
|
||||
var modifiedAtProperty = entityType.FindProperty("ModifiedAt");
|
||||
if (modifiedAtProperty != null)
|
||||
{
|
||||
modelBuilder.Entity(entityType.ClrType)
|
||||
.Property("ModifiedAt")
|
||||
.HasDefaultValueSql("GETUTCDATE()");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override int SaveChanges()
|
||||
{
|
||||
UpdateTimestamps();
|
||||
return base.SaveChanges();
|
||||
}
|
||||
|
||||
public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
UpdateTimestamps();
|
||||
return base.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
private void UpdateTimestamps()
|
||||
{
|
||||
var entities = ChangeTracker.Entries()
|
||||
.Where(e => e.State == EntityState.Added || e.State == EntityState.Modified);
|
||||
|
||||
foreach (var entity in entities)
|
||||
{
|
||||
// Try to set CreatedAt for new entities
|
||||
if (entity.State == EntityState.Added)
|
||||
{
|
||||
var createdAtProperty = entity.Properties.FirstOrDefault(p => p.Metadata.Name == "CreatedAt");
|
||||
if (createdAtProperty != null)
|
||||
{
|
||||
createdAtProperty.CurrentValue = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
// Ensure IsDeleted and IsCancelled have default values for Layer entities
|
||||
if (entity.Entity is Layer)
|
||||
{
|
||||
var isDeletedProperty = entity.Properties.FirstOrDefault(p => p.Metadata.Name == "IsDeleted");
|
||||
if (isDeletedProperty != null && isDeletedProperty.CurrentValue == null)
|
||||
{
|
||||
isDeletedProperty.CurrentValue = false;
|
||||
}
|
||||
|
||||
var isCancelledProperty = entity.Properties.FirstOrDefault(p => p.Metadata.Name == "IsCancelled");
|
||||
if (isCancelledProperty != null && isCancelledProperty.CurrentValue == null)
|
||||
{
|
||||
isCancelledProperty.CurrentValue = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Always update ModifiedAt
|
||||
var modifiedAtProperty = entity.Properties.FirstOrDefault(p => p.Metadata.Name == "ModifiedAt");
|
||||
if (modifiedAtProperty != null)
|
||||
{
|
||||
modifiedAtProperty.CurrentValue = DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
31
DiunaBI.Infrastructure/Data/DesignTimeDbContextFactory.cs
Normal file
31
DiunaBI.Infrastructure/Data/DesignTimeDbContextFactory.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Design;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace DiunaBI.Infrastructure.Data;
|
||||
|
||||
public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory<AppDbContext>
|
||||
{
|
||||
public AppDbContext CreateDbContext(string[] args)
|
||||
{
|
||||
var configuration = new ConfigurationBuilder()
|
||||
.SetBasePath(Path.Combine(Directory.GetCurrentDirectory(), "../DiunaBI.API"))
|
||||
.AddJsonFile("appsettings.json", optional: false)
|
||||
.AddJsonFile("appsettings.Development.json", optional: true)
|
||||
.Build();
|
||||
|
||||
var optionsBuilder = new DbContextOptionsBuilder<AppDbContext>();
|
||||
|
||||
var connectionString = configuration.GetConnectionString("SQLDatabase");
|
||||
if (string.IsNullOrEmpty(connectionString))
|
||||
{
|
||||
throw new InvalidOperationException("Connection string 'SQLDatabase' not found in appsettings.json");
|
||||
}
|
||||
|
||||
optionsBuilder.UseSqlServer(connectionString);
|
||||
|
||||
return new AppDbContext(optionsBuilder.Options);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user