DoomerDGR8
DoomerDGR8

Reputation: 5042

Setting up for selective auditing in same DbContext

I just stumbled onto Audit.Net and I'm hooked. I went through the Audit.Net Entity Framework (6) documentation and am a bit lost in the output part.

My solution is a bit many-layers design:

Reference: My EDMX is named Focus

Usage

I manage to modify the FocusModel.Context.tt from:

partial class <#=code.Escape(container)#> : DbContext

To:

partial class <#=code.Escape(container)#> : Audit.EntityFramework.AuditDbContext

Configuration

I found the default setting for Mode, IncludeEntityObjects, & AuditEventType were to my liking. the attribute for Include/Ignore entities/properties were straightforward as well.

Output

This is where I'm confused. I need to audit to the same database preferably to Audit tables for selected entities. Every entity in my database has composite PKs. How do I set the output mode in this scenario? Also, in my solution setup, the starting point for all projects that are behind the WCF Service is the WCF service itself. Does this mean that the point to Fluent-API-configure Audit.Net is here?

Upvotes: 1

Views: 1335

Answers (1)

thepirat000
thepirat000

Reputation: 13114

Have you seen the main Audit.NET documentation, specifically the output data providers?

I need to audit to the same database preferably to Audit tables for selected entities. Every entity in my database has composite PKs.

So you can use the EF data provider. It works with any kind of primary key.

How do I set the output mode in this scenario?

I'm not sure what do you mean by output mode, but I'm guessing you ask about OptIn/OptOut to ignore your audit entities to be audited. If that's the case you have multiple options, like using AuditIgnore attribute on your audit POCO classes, or via the fluent-api OptIn()/OptOut() methods. See example below.

The starting point for all projects that are behind the WCF Service is the WCF service itself. Does this mean that the point to Fluent-API-configure Audit.Net is here?

You can configure the Audit.NET library in any place, but you must do it before any audit event creation, so it is recommended to be on your startup code, as soon as your app or service starts.

Sample code

The following is a minimal example showing how you can configure the Audit.NET and Audit.EntityFramework libraries.

Suppose you have the following schema:

public class Student
{
    public int PK_1 { get; set; }
    public string PK_2 { get; set; }
    public string Name { get; set; }
}

public class Student_Audit
{
    public int PK_1 { get; set; }
    public string PK_2 { get; set; }
    public string Name { get; set; }

    public DateTime AuditDate { get; set; }
    public string AuditAction { get; set; }
}

public class SchoolContext : AuditDbContext
{
    protected override void OnModelCreating(ModelBuilder modelBuilder) //<--Tip: its not DbModelBuilder, its Microsoft.EntityFrameworkCore.ModelBuilder 
    {
        modelBuilder.Entity<Student>().HasKey(c => new { c.PK_1, c.PK_2 });
        modelBuilder.Entity<Student_Audit>().HasKey(c => new { c.PK_1, c.PK_2, c.AuditDate });
    }
    public DbSet<Student> Students { get; set; }
    public DbSet<Student_Audit> Students_Audit { get; set; }
}

You can configure the library on your startup code as follows:

// Setup audit to use the EF data provider
Audit.Core.Configuration.Setup()
    .UseEntityFramework(_ => _
        .AuditTypeExplicitMapper(m => m
            // Map Student to Student_Audit
            .Map<Student, Student_Audit>((ev, ent, studentAudit) =>     
            {
                //add the action name and the date to the audit entity
                studentAudit.AuditAction = ent.Action;
                studentAudit.AuditDate = DateTime.UtcNow;
            })));

// Configure the EF audit behavior
Audit.EntityFramework.Configuration.Setup()
    .ForContext<SchoolContext>(_ => _.IncludeEntityObjects())   
    .UseOptOut()
        .Ignore<Student_Audit>(); // Do not audit the audit tables

And a test case:

using (var db = new SchoolContext())
{
    db.Database.EnsureCreated();
    var st = new Student() { PK_1 = 1, PK_2 = "one", Name = "John" };
    db.Students.Add(st);
    db.SaveChanges();
}

Will generate the following:

enter image description here

Upvotes: 1

Related Questions