using CloudBuilder.Core.DatabaseAccessor.Entity; using CloudBuilder.Core.DependencyInjection.EFCore; using CloudBuilder.Core.Policy; using CloudBuilder.Core.Service; using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore; using Microsoft.IdentityModel.JsonWebTokens; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace CloudBuilder.Core.DatabaseAccessor { public class SecondaryDbContext : DbContext { public const string SECONDARY_DB_CONTEXT = "SecondaryDbContext"; public IEnumerable> _entityManagers; private readonly IServiceProvider _serviceProvider; private readonly IHttpContextAccessor httpContextAccessor; public SecondaryDbContext(DbContextOptions options, IEnumerable> entityManagers, IServiceProvider serviceProvider, IHttpContextAccessor httpContextAccessor) : base(options) { _entityManagers = entityManagers; _serviceProvider = serviceProvider; this.httpContextAccessor = httpContextAccessor; } public override int SaveChanges(bool acceptAllChangesOnSuccess) { try { SavingChangesEvent(); return base.SaveChanges(acceptAllChangesOnSuccess); } catch (Exception ex) { if (ex.Message.Contains("data may have been modified or deleted since entities were loaded.")) { throw new ValidatedException(CoreMessagePolicy.GetInstance().ComposeMessage(CoreMessagePolicy.THE_DATA_HAS_BEEN_MODIFIED)); } throw new ValidatedException(ex.InnerException?.Message ?? ex.Message); } } public void SavingChangesEvent() { var entities = this.ChangeTracker.Entries() .Where(u => (u.State == EntityState.Modified || u.State == EntityState.Deleted || u.State == EntityState.Added)).ToList(); if (entities == null || entities.Count < 1) return; string uid = this.httpContextAccessor.HttpContext?.User?.Identity?.Name; if (string.IsNullOrEmpty(uid)) { uid = string.Empty; string token = GetJwtBearerToken(httpContextAccessor.HttpContext!); if (!string.IsNullOrEmpty(token)) { try { JsonWebToken json = new JsonWebTokenHandler().ReadJsonWebToken(token); uid = json.GetClaim(ClaimPolicy.CLAINM_USERID).Value; } catch (Exception) { } } } foreach (var entity in entities) { if (!(entity.State == EntityState.Added || entity.State == EntityState.Modified)) continue; // 获取所有实体有效属性,排除 [NotMapper] 属性 var props = entity.OriginalValues.Properties; // 获取实体当前(现在)的值 var currentValues = entity.CurrentValues; // 遍历所有属性 foreach (var prop in props) { // 获取属性名 var propName = prop.Name; if (propName == IEntityAudited.CREATED_BY && entity.State == EntityState.Added) { currentValues[propName] = uid; continue; } if (propName == IEntityAudited.CREATED_DATETIME && entity.State == EntityState.Added) { currentValues[propName] = DateTime.Now; continue; } if (propName == IEntityAudited.UPDATED_BY) { currentValues[propName] = uid; continue; } if (propName == IEntityAudited.UPDATED_DATETIME) { currentValues[propName] = DateTime.Now; continue; } } } } protected override void OnModelCreating(ModelBuilder builder) { foreach (IMasterRegistEntityType entityManager in _entityManagers) { entityManager.RegistEntity(builder); } base.OnModelCreating(builder); } public string GetJwtBearerToken(HttpContext httpContext, string headerKey = "Authorization", string tokenPrefix = "Bearer ") { if (httpContext == null) return null; // 判断请求报文头中是否有 "Authorization" 报文头 var bearerToken = httpContext.Request.Headers[headerKey].ToString(); if (string.IsNullOrWhiteSpace(bearerToken)) return default; var prefixLenght = tokenPrefix.Length; return bearerToken.StartsWith(tokenPrefix, true, null) && bearerToken.Length > prefixLenght ? bearerToken[prefixLenght..] : default; } } }