我正在开发一个ASP.NET Core3.1Web应用程序。我想在数据库中持久化数据时添加审计跟踪/日志。
我从this SO answer那里得到灵感,开始在一个测试项目中使用Audit.NET。
以下是我的目标(类似于相关的SO线程):
将审计记录存储在不同的数据库中:几乎使用额外的AppAuditDbContext;
AppAuditDbContext;
AppAuditDbContext和DataAnnotations进行反思,完成了:到DO此时,我可以创建一个独立的已审计实体,并检索对审计数据库的正确审计。
但是,虽然我可以成功地删除带有其子实体的父实体,并获得父实体和子实体的审计数据,但对于这样的场景,我不知道如何从DB获得分组审计数据。
我试着使用Audit.NET EntityFramework的EntityFrameworkEvent.TransactionId和EntityFrameworkEvent.AmbientTransactionId,但它们都是DB上的null。
这是我的便便
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);
}
}这是范围的Delete控制器操作。
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配置为能够查询审核数据库以获得分组审核数据?
下面是Id为5的作用域的审核跟踪。

Audit_Scope表
下面是带有ScopeId #5的作业的审核跟踪。

Audit_Job表
考虑到所提供的数据,假设我希望阅读范围的删除审计(在本例中,是从Audit_Scope表中的Audit_Scope #9 ),包括对其子作业的删除审计(在本例中,是从Audit_Job表中的AuditId #10 )。我怎样才能做到这一点?
谢谢你,马泰奥
发布于 2020-04-30 07:01:27
目前,我刚刚在实体中添加了一个自定义字段。我在使用Guid的自定义操作中评估它。
// EF AuditEventId per scope
Audit.Core.Configuration.AddCustomAction(ActionType.OnScopeCreated, scope =>
{
var id = Guid.NewGuid();
scope.SetCustomField("AuditScopeId", id);
});这样,与同一个审计事件相关的Scope表记录和Job表记录都将包含相同的AuditScopeId值。
https://stackoverflow.com/questions/61385646
复制相似问题