Latest post

Update audit fields automatically using Entity Framework

I use this snippet to make sure I am always setting the audit fields globally so you can implement in one place and you are done with the auditing part. There's no need to set audit fields in every class.

Pre-requisites:
  • The following database table columns must be present in at least 1 database table:
    • CreatedByUserID (int)
    • CreatedDate (datetime)
    • LastUpdatedByUserID (int)
    • LastUpdatedDate (datetime)
  • A DbContext has been generated for your database


This is what codes below will do in summary:
  • Update audit column values every time context.SaveChanges() is called.
  • If the entity is being modified, update the LastUpdatedByUserID  and LastUpdatedDate values
  • If the entity is not being modified, it assumes a new record being inserted. Therefore, it will set the CreatedByUserID and CreatedDate values.

LET'S BEGIN!

(optional): Create an interface for dependency injection to pass the connection string.

public interface IContextConfig
{
 string ConnectionString { get; }
}


Create the a new class. The namespace and class name must be the same as what you have in your generated DbContext (Update the namespace and class name in the code below).

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using NEISTracker.Data.Interfaces;
using System;
using System.Threading;
using System.Threading.Tasks;

namespace MyProject.Data
{
    public partial class MyDBContext : DbContext
 {

        private readonly string _connectionString;
        public MyDBContext(IContextConfig contextConfig)
        {
            _connectionString = contextConfig.ConnectionString;
        }

        public int UserID { get; set; }

        public override int SaveChanges()
  {
   UpdateAuditFields();
   return base.SaveChanges();
  }

  public override Task SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default(CancellationToken))
  {
   UpdateAuditFields();
   return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
  }

  private void UpdateAuditFields()
  {
            foreach (var entry in ChangeTracker.Entries())
            {
                if (entry.State == EntityState.Added || entry.State == EntityState.Modified)
                {
                    foreach (var property in entry.Properties)
                    {
                        var propertyName = property.Metadata.Name.ToLower();

                        if (entry.State == EntityState.Modified)
                        {
                            if (propertyName == "lastupdatedbyuserid")
                            {
                                property.CurrentValue = UserID; //userid
                            }
                            else if (propertyName == "lastupdateddate")
                            {
                                property.CurrentValue = DateTime.Now;
                            }
                        }
                        else //it's an insert...
                        {
                            if (propertyName == "createdbyuserid")
                            {
                                property.CurrentValue = UserID;
                            }
                            else if (propertyName == "createddate")
                            {
                                property.CurrentValue = DateTime.Now;
                            }
                        }
                    }
                }
            }
        }
 }
}

To use it:

IContextConfig config = new ContextConfig();
var context = new MyDBContext(config);


Set the user ID that will be used to set the value for CreatedByUserID and LastUpdatedByUserID.

context.UserID = 2; //2 is just a made up value, you need to dynamically pass the current user. 


Create new or modify existing entity that contain audit columns, then call context.SaveChanges();

context.SaveChanges();

Check the database table to verify that it correctly set values to the audit fields.
There you have it. Happy coding!

Comments

Popular posts from this blog

Entity Framework Core Custom Pluralizer - .Net Core