我正在开发 ASP.NET Core 3.1 Web 应用程序。我想在数据库上保存数据时添加审计跟踪/日志。
我的灵感来自 this SO answer开始在测试项目中使用 Audit.NET。
这是我的目标(类似于相关的 SO 线程):
AppAuditDbContext
完成; AppAuditDbContext
; 操作数据库和审计数据库应该是无缝的:完成 通过对额外的反射(reflection)
AppAuditDbContext
和 DataAnnotations
关于被审计实体; 此时,我可以 CRUD 一个独立的审计实体,并在审计数据库上检索正确的审计。
但是,虽然我可以成功删除父实体及其子实体并获取父实体和子实体的审计数据,但我无法弄清楚如何从数据库中获取分组审计数据以用于此类场景。
我尝试使用 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);
}
}
这是范围的删除 Controller 操作。
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));
}
}
此 Controller 操作从 EF 的角度工作。它还审核父和子删除操作,但我不知道如何将子审核记录与父审核记录相关联
我应该在代码中的某处添加一个 AuditScope 吗?请问,我如何配置 Audit.NET 以便能够查询审计数据库以获取分组审计数据?
这是 ID 为 #5 的作用域的审计跟踪。
Audit_Scope 表
这是具有 ScopeId #5 的作业的审计跟踪。
Audit_Job 表
鉴于提供的数据,假设我想读取范围的删除审计(在本例中为 Audit_Scope 表中的 AuditId #9),包括其子作业的删除审计(在本例中为 Audit_Job 表中的 AuditId #10) .我怎样才能做到这一点?
谢谢,
马泰奥
最佳答案
目前我刚刚为我的实体添加了一个自定义字段。
我在带有 Guid 的自定义操作中重视它。
// EF AuditEventId per scope
Audit.Core.Configuration.AddCustomAction(ActionType.OnScopeCreated, scope =>
{
var id = Guid.NewGuid();
scope.SetCustomField("AuditScopeId", id);
});
这样我俩的
Scope
和 Job
与同一审计事件相关的表记录将保持相同 AuditScopeId
值(value)。
关于c# - Audit.NET Entity Framework Core - 相关实体管理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61385646/