清理dbcontext 记录稽查代码位置
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
parent
6276e0611a
commit
80a60dff38
|
@ -1,56 +0,0 @@
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using IRaCIS.Core.Domain.Models;
|
|
||||||
|
|
||||||
namespace IRaCIS.Core.Infra.EFCore
|
|
||||||
{
|
|
||||||
#region AuditContext
|
|
||||||
public class AuditContext : DbContext
|
|
||||||
{
|
|
||||||
//传递委托进来写日志
|
|
||||||
|
|
||||||
private readonly string _connectionString;
|
|
||||||
|
|
||||||
public AuditContext(string connectionString)
|
|
||||||
{
|
|
||||||
_connectionString = connectionString;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
|
||||||
=> optionsBuilder.UseSqlServer(_connectionString);
|
|
||||||
|
|
||||||
public DbSet<SaveChangesAudit> SaveChangesAudits { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class SaveChangesAudit
|
|
||||||
{
|
|
||||||
public Guid Id { get; set; }
|
|
||||||
//public Guid AuditId { get; set; }
|
|
||||||
public DateTime StartTime { get; set; }
|
|
||||||
public DateTime EndTime { get; set; }
|
|
||||||
public bool Succeeded { get; set; } = false;
|
|
||||||
public string ErrorMessage { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
public ICollection<EntityAudit> Entities { get; } = new List<EntityAudit>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public class EntityAudit: IAuditAddWithUserName
|
|
||||||
{
|
|
||||||
public Guid Id { get; set; }
|
|
||||||
public Guid AlterId { get; set; }=Guid.Empty;
|
|
||||||
public Guid SaveChangesAuditId { get; set; }
|
|
||||||
public EntityState State { get; set; }
|
|
||||||
public string AuditMessage { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public SaveChangesAudit SaveChangesAudit { get; set; }
|
|
||||||
|
|
||||||
public string CreateUser { get; set; } = string.Empty;
|
|
||||||
public Guid CreateUserId { get; set; }=Guid.Empty;
|
|
||||||
public DateTime CreateTime { get; set; }=DateTime.Now;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
|
|
@ -162,8 +162,6 @@ namespace IRaCIS.Core.Infra.EFCore
|
||||||
|
|
||||||
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken())
|
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken())
|
||||||
{
|
{
|
||||||
// 采用触发器的方式 设置 CreateUserId CreateTime UpdateTime UpdateUserId 稽查实体里面没有这四个字段的值 因为先后顺序的原因
|
|
||||||
await AddAudit();
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -222,28 +220,7 @@ namespace IRaCIS.Core.Infra.EFCore
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public async Task AddAudit()
|
|
||||||
{
|
|
||||||
|
|
||||||
//触发器里面提交事务 业务方法里面提交事务 会记录两次
|
|
||||||
var inspectionGeneralIdList = ChangeTracker.Entries().Where(t => typeof(DataInspection).IsAssignableFrom(t.Entity.GetType())).Select(t => ((DataInspection)t.Entity).GeneralId).ToList();
|
|
||||||
|
|
||||||
var entities = ChangeTracker.Entries().Where(u => (u.State == EntityState.Modified || u.State == EntityState.Deleted || u.State == EntityState.Added))
|
|
||||||
.Where(t => !typeof(DataInspection).IsAssignableFrom(t.Entity.GetType()) && !inspectionGeneralIdList.Contains(((Entity)t.Entity).Id))
|
|
||||||
.ToList();
|
|
||||||
AuditingData auditingData = new AuditingData(this, _userInfo);
|
|
||||||
|
|
||||||
//await auditingData.IncomingEntitys(entities);
|
|
||||||
|
|
||||||
|
|
||||||
if (entities.Count > 0)
|
|
||||||
{
|
|
||||||
await auditingData.InsertAddEntitys(entities);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Doctor
|
#region Doctor
|
||||||
public virtual DbSet<Dictionary> Dictionary { get; set; }
|
public virtual DbSet<Dictionary> Dictionary { get; set; }
|
||||||
|
@ -399,7 +376,6 @@ namespace IRaCIS.Core.Infra.EFCore
|
||||||
public virtual DbSet<TrialAudit> TrialAudit { get; set; }
|
public virtual DbSet<TrialAudit> TrialAudit { get; set; }
|
||||||
public virtual DbSet<UserType> UserType { get; set; }
|
public virtual DbSet<UserType> UserType { get; set; }
|
||||||
|
|
||||||
public virtual DbSet<SaveChangesAudit> SaveChangesAudits { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
using IRaCIS.Core.Domain.Models;
|
using IRaCIS.Core.Domain.Models;
|
||||||
using IRaCIS.Core.Domain.Share;
|
using IRaCIS.Core.Domain.Share;
|
||||||
|
using IRaCIS.Core.Infra.EFCore.Common;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Diagnostics;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.ChangeTracking;
|
||||||
using Microsoft.EntityFrameworkCore.Diagnostics;
|
using Microsoft.EntityFrameworkCore.Diagnostics;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
@ -23,8 +26,12 @@ public class AuditEntityInterceptor(IUserInfo _userInfo) : SaveChangesIntercepto
|
||||||
public override ValueTask<InterceptionResult<int>> SavingChangesAsync(DbContextEventData eventData,
|
public override ValueTask<InterceptionResult<int>> SavingChangesAsync(DbContextEventData eventData,
|
||||||
InterceptionResult<int> result, CancellationToken cancellationToken = default)
|
InterceptionResult<int> result, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
|
//审计时间
|
||||||
AuditEntities(eventData.Context);
|
AuditEntities(eventData.Context);
|
||||||
|
|
||||||
|
//IRC稽查 放在savechange 之前 不影响之前的逻辑
|
||||||
|
IRCDataInspection(eventData.Context);
|
||||||
|
|
||||||
return base.SavingChangesAsync(eventData, result, cancellationToken);
|
return base.SavingChangesAsync(eventData, result, cancellationToken);
|
||||||
}
|
}
|
||||||
public override InterceptionResult<int> SavingChanges(DbContextEventData eventData, InterceptionResult<int> result)
|
public override InterceptionResult<int> SavingChanges(DbContextEventData eventData, InterceptionResult<int> result)
|
||||||
|
@ -103,7 +110,23 @@ public class AuditEntityInterceptor(IUserInfo _userInfo) : SaveChangesIntercepto
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void IRCDataInspection(DbContext? context)
|
||||||
|
{
|
||||||
|
//触发器里面提交事务 业务方法里面提交事务 会记录两次
|
||||||
|
var inspectionGeneralIdList = context.ChangeTracker.Entries().Where(t => typeof(DataInspection).IsAssignableFrom(t.Entity.GetType())).Select(t => ((DataInspection)t.Entity).GeneralId).ToList();
|
||||||
|
|
||||||
|
var entities = context.ChangeTracker.Entries().Where(u => (u.State == EntityState.Modified || u.State == EntityState.Deleted || u.State == EntityState.Added))
|
||||||
|
.Where(t => !typeof(DataInspection).IsAssignableFrom(t.Entity.GetType()) && !inspectionGeneralIdList.Contains(((Entity)t.Entity).Id))
|
||||||
|
.ToList();
|
||||||
|
AuditingData auditingData = new AuditingData((IRaCISDBContext)context, _userInfo);
|
||||||
|
|
||||||
|
|
||||||
|
if (entities.Count > 0)
|
||||||
|
{
|
||||||
|
auditingData.InsertAddEntitys(entities).GetAwaiter().GetResult();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
|
@ -11,6 +11,8 @@ using MassTransit;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Infra.EFCore.Interceptor
|
namespace IRaCIS.Core.Infra.EFCore.Interceptor
|
||||||
{
|
{
|
||||||
|
// ISendEndpoint:提供了Send方法,用于发送命令。
|
||||||
|
//IPublishEndpoint:提供了Publish方法,用于发布事件。
|
||||||
public class DispatchDomainEventsInterceptor(IPublishEndpoint publishEndpoint) : SaveChangesInterceptor
|
public class DispatchDomainEventsInterceptor(IPublishEndpoint publishEndpoint) : SaveChangesInterceptor
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -1,148 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using IRaCIS.Core.Domain.Models;
|
|
||||||
using IRaCIS.Core.Infra.EFCore;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.ChangeTracking;
|
|
||||||
using Microsoft.EntityFrameworkCore.Diagnostics;
|
|
||||||
|
|
||||||
public class AuditingInterceptor : ISaveChangesInterceptor
|
|
||||||
{
|
|
||||||
private readonly string _connectionString;
|
|
||||||
private SaveChangesAudit _audit;
|
|
||||||
|
|
||||||
public AuditingInterceptor(string connectionString)
|
|
||||||
{
|
|
||||||
_connectionString = connectionString;
|
|
||||||
}
|
|
||||||
|
|
||||||
#region SavingChanges
|
|
||||||
public async ValueTask<InterceptionResult<int>> SavingChangesAsync(
|
|
||||||
DbContextEventData eventData,
|
|
||||||
InterceptionResult<int> result,
|
|
||||||
CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
_audit = CreateAudit(eventData.Context);
|
|
||||||
|
|
||||||
await Task.CompletedTask;
|
|
||||||
return result;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public InterceptionResult<int> SavingChanges(
|
|
||||||
DbContextEventData eventData,
|
|
||||||
InterceptionResult<int> result)
|
|
||||||
{
|
|
||||||
_audit = CreateAudit(eventData.Context);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region SavedChanges
|
|
||||||
|
|
||||||
public async ValueTask<int> SavedChangesAsync(
|
|
||||||
SaveChangesCompletedEventData eventData,
|
|
||||||
int result,
|
|
||||||
CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
if (_audit.Entities.Count > 0)
|
|
||||||
{
|
|
||||||
var auditContext = eventData.Context as IRaCISDBContext;
|
|
||||||
_audit.Succeeded = true;
|
|
||||||
auditContext.SaveChangesAudits.Add(_audit);
|
|
||||||
_audit.EndTime = DateTime.Now;
|
|
||||||
|
|
||||||
await auditContext.SaveChangesAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region SaveChangesFailed
|
|
||||||
public void SaveChangesFailed(DbContextErrorEventData eventData)
|
|
||||||
{
|
|
||||||
using (var auditContext = new AuditContext(_connectionString))
|
|
||||||
{
|
|
||||||
auditContext.Attach(_audit);
|
|
||||||
_audit.Succeeded = false;
|
|
||||||
_audit.EndTime = DateTime.Now;
|
|
||||||
_audit.ErrorMessage = eventData.Exception.Message;
|
|
||||||
|
|
||||||
auditContext.SaveChanges();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task SaveChangesFailedAsync(
|
|
||||||
DbContextErrorEventData eventData,
|
|
||||||
CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
using (var auditContext = new AuditContext(_connectionString))
|
|
||||||
{
|
|
||||||
auditContext.Attach(_audit);
|
|
||||||
_audit.Succeeded = false;
|
|
||||||
_audit.EndTime = DateTime.Now;
|
|
||||||
_audit.ErrorMessage = eventData.Exception.InnerException?.Message;
|
|
||||||
|
|
||||||
await auditContext.SaveChangesAsync(cancellationToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region CreateAudit
|
|
||||||
private static bool NeedAudit(EntityEntry entityEntry)
|
|
||||||
{
|
|
||||||
var type = entityEntry.Entity.GetType();
|
|
||||||
return type != typeof(EntityAudit) && type != typeof(SaveChangesAudit) && type != typeof(DicomSeries) && type != typeof(DicomInstance) && type != typeof(TrialAudit);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static SaveChangesAudit CreateAudit(DbContext context)
|
|
||||||
{
|
|
||||||
context.ChangeTracker.DetectChanges();
|
|
||||||
|
|
||||||
var audit = new SaveChangesAudit { StartTime = DateTime.Now };
|
|
||||||
|
|
||||||
foreach (var entry in context.ChangeTracker.Entries().Where(t => NeedAudit(t)))
|
|
||||||
{
|
|
||||||
var auditMessage = entry.State switch
|
|
||||||
{
|
|
||||||
EntityState.Deleted => CreateDeletedMessage(entry),
|
|
||||||
EntityState.Modified => CreateModifiedMessage(entry),
|
|
||||||
EntityState.Added => CreateAddedMessage(entry),
|
|
||||||
_ => null
|
|
||||||
};
|
|
||||||
|
|
||||||
if (auditMessage != null)
|
|
||||||
{
|
|
||||||
var alterIdStr = entry.CurrentValues["Id"].ToString();
|
|
||||||
audit.Entities.Add(new EntityAudit { State = entry.State, AuditMessage = auditMessage, AlterId = Guid.Parse(alterIdStr) });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return audit;
|
|
||||||
|
|
||||||
string CreateAddedMessage(EntityEntry entry)
|
|
||||||
=>
|
|
||||||
entry.Properties.Aggregate(
|
|
||||||
$"Inserting {entry.Metadata.DisplayName()} with ",
|
|
||||||
(auditString, property) => auditString + $"{property.Metadata.Name}: '{property.CurrentValue}' ");
|
|
||||||
|
|
||||||
string CreateModifiedMessage(EntityEntry entry)
|
|
||||||
=> entry.Properties.Where(property => property.IsModified || property.Metadata.IsPrimaryKey()).Aggregate(
|
|
||||||
$"Updating {entry.Metadata.DisplayName()} with ",
|
|
||||||
(auditString, property) => auditString + $"{property.Metadata.Name}: '{property.CurrentValue}' ");
|
|
||||||
|
|
||||||
string CreateDeletedMessage(EntityEntry entry)
|
|
||||||
=> entry.Properties.Where(property => property.Metadata.IsPrimaryKey()).Aggregate(
|
|
||||||
$"Deleting {entry.Metadata.DisplayName()} with ",
|
|
||||||
(auditString, property) => auditString + $"{property.Metadata.Name}: '{property.CurrentValue}' ");
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in New Issue