using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using Infrastructure.Domain; using Infrastructure.Extensions; using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; namespace Infrastructure.Data { public class EfDbContext : DbContext { private readonly IHttpContextAccessor _httpContext; public static readonly LoggerFactory MyLoggerFactory = new LoggerFactory( //new[] //{ // //new ConsoleLoggerProvider((_, __) => true, true) //} ); public EfDbContext(DbContextOptions options, IHttpContextAccessor httpContext) : base(options) { this._httpContext = httpContext; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseLoggerFactory(MyLoggerFactory); optionsBuilder.EnableSensitiveDataLogging(); base.OnConfiguring(optionsBuilder); } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.RemovePluralizingTableNameConvention(); OnModelCreatingAction(modelBuilder); foreach (var entity in modelBuilder.Model.GetEntityTypes()) { if (entity.GetProperties().Any(o => o.Name == "Id")) { modelBuilder.Entity(entity.Name).HasKey("Id"); modelBuilder.Entity(entity.Name).Property("Id").ValueGeneratedNever(); } if (entity.GetProperties().Any(o => o.Name == "RowVersion")) { modelBuilder.Entity(entity.Name).Property("RowVersion")?.IsConcurrencyToken().ValueGeneratedNever(); } } } public override int SaveChanges() { this.ChangeTracker.DetectChanges(); var entries = this.ChangeTracker.Entries().Where(o => o.State == EntityState.Added || o.State == EntityState.Modified || o.State == EntityState.Deleted).ToList(); foreach (var entry in entries) { var entity = entry.Entity as BaseEntity; if (entity is IValidatableObject) { var validationResults = new List(); if (!Validator.TryValidateObject(entry.Entity, new ValidationContext(entity, null, null), validationResults, true)) { throw new EntityInvalidException(validationResults, $"{entity.GetType().FullName} valid error"); } } if (entity is IVersionEntity) { (entity as IVersionEntity).RowVersion = Guid.NewGuid().ToString(); } var now = DateTime.UtcNow; var userName = this._httpContext?.HttpContext?.User?.Identity?.Name ?? "admin"; if (entry.State == EntityState.Added) { entity.CreateOn = now; entity.CreateBy = userName; } else if (entry.State == EntityState.Modified) { entity.UpdateOn = now; entity.UpdateBy = userName; } Console.WriteLine($"{entity.GetType().Name}:{entry.State.ToString()}:{entry.OriginalValues.ToObject().ToJson()}/{entry.CurrentValues.ToObject().ToJson()}"); } try { return base.SaveChanges(); } catch (Exception ex) { ex.PrintStack(); var list = entries.Select(o => o.Entity).ToList(); Console.WriteLine(list.ToJson()); throw new Exception(ex.Message, ex); } } public static Action OnModelCreatingAction; } }