我正在使用ASP.NET Core 3.1 Web应用程序。在将数据持久存储在数据库中时,我想添加审计跟踪/日志。
我从this SO answer得到启发,开始在一个测试项目中使用Audit.NET。
这是我的目标(类似于相关的SO线程):
AppAuditDbContext
; AppAuditDbContext
进行反思; AppAuditDbContext
和DataAnnotations
进行反思; 这时,我可以对一个独立的审计实体进行CRUD,并在Audit数据库上检索正确的审计。
但是,尽管我可以成功删除带有其子级的父实体并获取父子实体的审计数据,但是我无法弄清楚在这种情况下如何从数据库中获取分组审计数据。
我尝试使用Audit.NET EntityFramework的EntityFrameworkEvent.TransactionId
和EntityFrameworkEvent.AmbientTransactionId
,但是它们都在数据库中null
。
这是我的POCO
public interface IAuditableEntity
{
[NotMapped]
string AuditAction { get; set; }
[NotMapped]
string AuditTransactionId { get; set; }
[NotMapped]
string AuditAmbientTransactionId { get; set; }
}
public class Scope : IAuditableEntity
{
[Key]
public int Id {get;set;}
public string Name { get; set; }
public virtual ICollection<Job> Jobs { get; set; }
[NotMapped]
string AuditAction { get; set; }
[NotMapped]
string AuditTransactionId { get; set; }
[NotMapped]
string AuditAmbientTransactionId { get; set; }
}
public class Job : IAuditableEntity
{
[Key]
public int Id {get;set;}
public int ScopeId { get; set; }
public virtual Scope Scope { get; set; }
[StringLength(128)]
public string Name { get; set; }
[NotMapped]
public string AuditAction { get; set; }
[NotMapped]
public string AuditTransactionId { get; set; }
[NotMapped]
public string AuditAmbientTransactionId { get; set; }
}
这是我的Audit.NET配置(来自Startup.cs)
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddDbContext<AppAuditDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("AuditConnection")));
#region Audit.NET
var auditDbContextOptions = new DbContextOptionsBuilder<AppAuditDbContext>()
.UseSqlServer(Configuration.GetConnectionString("AuditConnection"))
.Options;
Audit.Core.Configuration.Setup()
.UseEntityFramework(x => x
.UseDbContext<AppAuditDbContext>(auditDbContextOptions)
.AuditTypeNameMapper(typeName =>
{
return typeName;
}).AuditEntityAction<IAuditableEntity>((ev, ent, auditEntity) =>
{
var entityFrameworkEvent = ev.GetEntityFrameworkEvent();
if (entityFrameworkEvent == null) return;
auditEntity.AuditTransactionId = entityFrameworkEvent.TransactionId;
auditEntity.AuditAmbientTransactionId = entityFrameworkEvent.AmbientTransactionId;
auditEntity.AuditAction = ent.Action;
}));
#endregion
services.AddControllersWithViews();
}
// other stuff..
}
这是经过审核的上下文。
[AuditDbContext(IncludeEntityObjects = true)]
public class ApplicationDbContext : AuditDbContext
{
public ApplicationDbContext([NotNullAttribute] DbContextOptions<ApplicationDbContext> options) : base(options)
{
}
public DbSet<Scope> Scopes { get; set; }
public DbSet<Job> Jobs { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Scope>().ToTable("Scope");
modelBuilder.Entity<Job>().ToTable("Job");
}
public override int SaveChanges()
{
return base.SaveChanges();
}
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
{
return await base.SaveChangesAsync(cancellationToken);
}
}
这是作用域的“删除”控制器操作。
public class ScopeController : Controller
{
private readonly ApplicationDbContext _context;
public ScopeController(ApplicationDbContext context)
{
_context = context;
}
// Other controller actions...
// POST: Scope/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
var scope = await _context.Scopes.Include(s => s.Jobs).SingleOrDefaultAsync(w => w.Id == id);
// using _context.Scopes.FindAsync(id) instead does delete the children Jobs without auditing it
_context.Scopes.Remove(scope);
await _context.SaveChangesAsync().ConfigureAwait(false);
return RedirectToAction(nameof(Index));
}
}
此控制器动作从EF角度起作用。它还审核父级和子级删除操作,但是我不知道如何将子级审核记录与父级审核记录相关联 我应该在代码中的某处添加AuditScope吗?请,如何配置Audit.NET以查询Audit数据库以获取分组的审核数据?
这是ID为5的合并范围的审核跟踪。
Audit_Scope表
这是具有ScopeId#5的作业的审核记录。
Audit_Job表
鉴于提供的数据,假设我要读取范围的删除审核(在本例中为Audit_Scope表中的AuditId#9),包括对其子Jobs的删除审核(在本例中为AuditID#10从Audit_Job表)。我该如何实现?
谢谢, Matteo
答案 0 :(得分:2)
此刻,我刚刚向我的实体添加了一个自定义字段。 我非常重视使用Guid进行自定义操作的方法。
// EF AuditEventId per scope
Audit.Core.Configuration.AddCustomAction(ActionType.OnScopeCreated, scope =>
{
var id = Guid.NewGuid();
scope.SetCustomField("AuditScopeId", id);
});
通过这种方式,与同一审核事件相关的Scope
和Job
表记录都将具有相同的AuditScopeId
值。