Audit with Entity Framework

Asked

Viewed 824 times

3

I am wanting to do the audit tables of my entities. At first I thought to overwrite the method SaveChanges. I also thought of writing a method that will be doing the audit on my repository base. Using both forms, 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 the type of my entity so that I can save in the audit table of the same?

My code until then is 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;
} 

1 answer

1


Implementation Caseira

First you need to create a way to relate the Model log with the 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 ancestral class of all its Models, or an interface. In some projects I do, all the 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 on the second the date it was last modified, which is more or less like this:

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

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

public class ModelDeLogGenerico<T>
    where T: IEntityBase
{

}

Suppose now a Model any of your system:

public class Fruta 
{
    ...
}

His respective log will be:

public class LogFruta<Fruta>
{
    ...
}

Having this, we can now identify that LogFruta audita Fruta. The following Reflection-based code searches the assembly of your application which class has as generic argument the class Fruta:

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

Solutions Pronto

The Entityframework.Extended. has native ability to log for you. There’s an explanation here.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.