c# – Auditoria com Entity Framework

Question:

I want to make audit tables of my entities. At first I thought about overriding the SaveChanges method. I also thought about writing a method that will be auditing my repository base. Using both ways, I will have a single audit table for my entire system.

But for performance reasons I need each entity to have its log table.

What would be the best way to intercept my entity's type so that I can save it in the audit table of the entity?

My code so far looks like this:

public override int SaveChanges()
{
     var entriesAdicionadas = ChangeTracker.Entries().Where(e => e.State == EntityState.Added).ToList();

     var entriesModificadas = ChangeTracker.Entries().Where(e => e.State == EntityState.Modified).ToList();

     var entriesDeletadas = ChangeTracker.Entries().Where(e => e.State == EntityState.Deleted).ToList();
     foreach (var entry in entriesAdicionadas)
     {

     }
     int result = base.SaveChanges();

     foreach (var entry in entriesModificadas)
     {
         var nome = entry.Entity.GetType().Name;
     }

     base.SaveChanges();

     foreach (var entry in entriesDeletadas)
     {
         var nome = entry.Entity.GetType().Name;
     }

     return result;
} 

Answer:

Home Implementation

First you need to create a way to relate the Log Model with Model that will be audited. This can be done by declaring a Model with generic. For example:

public class ModelDeLogGenerico<T>
    where T: class
{

}

T doesn't have to be class . T can be an ancestor class of all your Models , or an interface. In some projects I do, all Models derive from an interface called IEntityBase , in which I force the Model to have two more properties: on the first record the date the record was created and the second the date it was modified for the last time, which goes something like this:

namespace MyProject.Models.Interfaces
{
    interface IEntityBase
    {
        DateTime LastModified { get; set; }
        DateTime CreatedOn { get; set; }
    }
}

This ensures that your Log Model cannot necessarily take any classes. The class to be valid needs to implement IEntityBase . My Log class, therefore, would look like this:

public class ModelDeLogGenerico<T>
    where T: IEntityBase
{

}

Now suppose any Model of your system:

public class Fruta 
{
    ...
}

Its respective Log will be:

public class LogFruta<Fruta>
{
    ...
}

Having that, we can now identify that LogFruta audits Fruta . The following code based on Reflection looks in your application's Assembly which class has the Fruta class as its generic argument:

var log = Assembly.GetExecutingAssembly().GetTypes().FirstOrDefault(t => t.GetGenericArguments()[0] == entry.GetType());

Ready-made solutions

EntityFramework.Extended has native logging capability for you. There's an explanation here .

Scroll to Top