You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
148 lines
6.4 KiB
148 lines
6.4 KiB
using Infrastructure.Domain;
|
|
using Infrastructure.Events;
|
|
using Infrastructure.Extensions;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.Extensions.Hosting;
|
|
using Microsoft.Extensions.Logging;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel.DataAnnotations;
|
|
using System.Linq;
|
|
|
|
namespace Infrastructure.Data
|
|
{
|
|
public class EfDbContext : DbContext
|
|
{
|
|
public static readonly ILoggerFactory MyLoggerFactory = LoggerFactory.Create(builder =>
|
|
{
|
|
builder.AddDebug();
|
|
});
|
|
|
|
protected readonly ILogger<EfDbContext> _logger;
|
|
protected readonly IHostEnvironment _env;
|
|
protected readonly IConfiguration _cfg;
|
|
protected readonly IEventPublisher _publisher;
|
|
|
|
public EfDbContext(DbContextOptions options, ILogger<EfDbContext> logger, IHostEnvironment env, IConfiguration cfg, IEventPublisher publisher) : base(options)
|
|
{
|
|
this._logger = logger;
|
|
this._env = env;
|
|
this._cfg = cfg;
|
|
this._publisher = publisher;
|
|
this.ChangeTracker.AutoDetectChangesEnabled = false;
|
|
}
|
|
|
|
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
|
{
|
|
optionsBuilder?.UseLoggerFactory(MyLoggerFactory);
|
|
optionsBuilder?.EnableSensitiveDataLogging();
|
|
}
|
|
|
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
|
{
|
|
if (modelBuilder is null)
|
|
{
|
|
throw new ArgumentNullException(nameof(modelBuilder));
|
|
}
|
|
var entityTypes = modelBuilder.Model.GetEntityTypes().ToList();
|
|
var tablePrefix = this._cfg.GetAppSetting("TablePrefix");
|
|
foreach (var entity in entityTypes)
|
|
{
|
|
if (!string.IsNullOrEmpty(tablePrefix))
|
|
{
|
|
entity.SetTableName($"{tablePrefix}_{entity.GetTableName()}");
|
|
}
|
|
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();
|
|
}
|
|
if (entity.GetProperties().Any(o => o.Name == "Created"))
|
|
{
|
|
modelBuilder.Entity(entity.Name).Property("Created").ValueGeneratedOnAdd();
|
|
}
|
|
if (entity.GetProperties().Any(o => o.Name == "Modified"))
|
|
{
|
|
modelBuilder.Entity(entity.Name).Property("Modified").ValueGeneratedOnUpdate();
|
|
}
|
|
if (entity.GetProperties().Any(o => o.Name == "Parent") && entity.GetProperties().Any(o => o.Name == "Children"))
|
|
{
|
|
modelBuilder.Entity(entity.Name).HasOne("Parent").WithMany("Children").HasForeignKey(new string[] { "ParentId" }).OnDelete(DeleteBehavior.SetNull);
|
|
if (entity.GetProperties().Any(o => o.Name == "Name"))
|
|
{
|
|
modelBuilder.Entity(entity.Name).Property("Name").IsRequired();
|
|
}
|
|
if (entity.GetProperties().Any(o => o.Name == "Number"))
|
|
{
|
|
modelBuilder.Entity(entity.Name).Property("Number").IsRequired();
|
|
}
|
|
}
|
|
modelBuilder.Entity(entity.Name).HasComment(entity.ClrType.GetDisplayName());
|
|
foreach (var prop in entity.GetProperties())
|
|
{
|
|
modelBuilder.Entity(entity.ClrType).Property(prop.Name).HasComment(prop.PropertyInfo.GetDisplayName());
|
|
}
|
|
}
|
|
}
|
|
|
|
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();
|
|
var events = new List<object>();
|
|
foreach (var entry in entries)
|
|
{
|
|
var entity = entry.Entity as BaseEntity;
|
|
if (entity is IValidatableObject)
|
|
{
|
|
var validationResults = new List<ValidationResult>();
|
|
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 = DateTimeOffset.UtcNow;
|
|
if (entry.State == EntityState.Added)
|
|
{
|
|
entity.Created = now;
|
|
events.Add(Activator.CreateInstance(typeof(EntityInserted<>).MakeGenericType(entry.Entity.GetType()), entry.Entity));
|
|
}
|
|
else if (entry.State == EntityState.Modified)
|
|
{
|
|
entity.Modified = now;
|
|
events.Add(Activator.CreateInstance(typeof(EntityUpdated<>).MakeGenericType(entry.Entity.GetType()), entry.Entity, entry.OriginalValues.ToObject()));
|
|
}
|
|
else if (entry.State == EntityState.Deleted)
|
|
{
|
|
events.Add(Activator.CreateInstance(typeof(EntityDeleted<>).MakeGenericType(entry.Entity.GetType()), entry.Entity));
|
|
}
|
|
this._logger.LogDebug($"{nameof(EfDbContext)}>{entity.GetType().Name}:{entry.State}");
|
|
}
|
|
try
|
|
{
|
|
var result = base.SaveChanges();
|
|
if (events.Count > 0)
|
|
{
|
|
events.ForEach(o => this._publisher.Publish(o));
|
|
}
|
|
return result;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ChangeTracker.Clear();
|
|
ex.PrintStack();
|
|
this._logger.LogError(ex.ToString());
|
|
throw;
|
|
}
|
|
}
|
|
}
|
|
} |