Search code examples
c#entity-framework-coreasp.net-core-webapi

Losing CreatedOn data when modifying a record in Entity Framework


I'm trying to save the AuditLog data in Entity Framework in my ASP.NET Core Web API, and I'm using SQLite as my database. I tried to override the SaveChangesAsync() method to track them.

But the CreatedBy and CreatedOn values are lost every time I modify a record.

Here's the overridden version of SaveChangesAsync() method and a sample entity:

private readonly IHttpContextAccessor _contextAccessor;

public EvaDbContext(DbContextOptions options, IHttpContextAccessor contextAccessor) : base(options)
{
    _contextAccessor = contextAccessor;
}

public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
{
    if (!_contextAccessor.IsLoginRequeust())
    {
        // Grab all entity entries
        var entityEntries = ChangeTracker.Entries().Where(e => e.Entity is DomainObject && (e.State == EntityState.Added || e.State == EntityState.Modified));
        var userId = _contextAccessor.GetUserId();

        foreach (var entityEntry in entityEntries)
        {
            // Add current datetime for modified state
            ((DomainObject)entityEntry.Entity).ModifiedOn = DateTime.Now;
            ((DomainObject)entityEntry.Entity).ModifiedBy = userId;

            // Add current datetime for added state
            if (entityEntry.State == EntityState.Added)
            {
                ((DomainObject)entityEntry.Entity).CreatedOn = DateTime.Now;
                ((DomainObject)entityEntry.Entity).CreatedBy = userId;
            }
        }
    }

    return await base.SaveChangesAsync(cancellationToken);
}

enter image description here


Solution

  • I actually achieved what I was looking for but I'm not happy with the solution, here's what I did:

    // Check if entry state is added mode
    var isAddedState = entityEntry.State == EntityState.Added;
    
    // Detect trackeble properties
    entityEntry.Property("ModifiedOn").CurrentValue = DateTime.Now;
    entityEntry.Property("ModifiedBy").CurrentValue = userId;
    entityEntry.Property("CreatedOn").CurrentValue = isAddedState ? DateTime.Now : entityEntry.Property("CreatedOn").OriginalValue;
    entityEntry.Property("CreatedBy").CurrentValue = isAddedState ? userId : entityEntry.Property("CreatedBy").OriginalValue;