Entity Framework Core - Generically assign dynamic values to common columns in code first

c# ef-code-first entity-framework-core sql-server

Question

I am trying to assign values to columns common in all tables using code at one place. My scenario is as below.

I have common columns in all tables like "CreatedBy", "CompanyId" which are derived from BaseEntity.

public abstract class BaseEntity
    {
        public DateTime? CreatedDateTime { get; set; }

        public DateTime? ModifiedDateTime { get; set; }

        public int? CreatedBy { get; set; }

        public int CompanyId { get; set; }

        public int? ModifiedBy { get; set; }
    }

Values like "CompanyId" can be set only at run time and not using SQL Server default values. When I manually assign this value while adding the entity in my repository, if there are any child entities will contain null values until I assign them manually. I am looking for a generic solution so that I don't have to assign these columns again and again and at every location.

1
0
9/26/2018 10:36:55 PM

Accepted Answer

To set all the common columns in all tables, override the SaveChanges and SaveChangesAsync method of DbContext as below.

public class MyContext : DbContext
    {
        public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken())
        {
            SetBaseValues();
            return base.SaveChangesAsync(cancellationToken);
        }

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

        private void SetBaseValues()
        {
            var addedEntries = ChangeTracker.Entries().Where(e => e.State == EntityState.Added);
            var utcNow = DateTime.UtcNow;
            foreach (var entry in addedEntries)
            {
                entry.Property("CreatedDateTime").CurrentValue = utcNow;
                entry.Property("CreatedBy").CurrentValue = UserData.GetCurrentUserId();
            }
            var modifiedEntries = ChangeTracker.Entries().Where(e => e.State == EntityState.Modified);
            foreach (var entry in modifiedEntries)
            {
                entry.Property("CreatedDateTime").IsModified = false;
                entry.Property("CreatedBy").IsModified = false;
                entry.Property("ModifiedDateTime").CurrentValue = utcNow;
                entry.Property("ModifiedBy").CurrentValue = UserData.GetCurrentUserId();
            }
        }
    }

Here, "UserData" is the class responsible for your session data like currently logged in user, current user's company id, etc. or you can replace this with any other relevant code in your application. This solution will run in every scenario and for nested/child entities as well. And, you will not need to assign these values again in your application anywhere.

0
12/20/2018 2:33:55 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow