DateCreated and DateModified in ASP.NET MVC 5

I am working on a Code-First project and I need a database to process DateCreated

and DateModified

.

The application runs in IIS Express using LocalDB on the dev machine and will use SQL Server 2012 on the deployment server running IIS 7.5.

I have the following model:

public class Person : IdentityUser {

  [Required]
  public string Name { get; set; }

  public Date DateOfBirth { get; set; }

  public string Address { get; set; }

  [DatabaseGeneratedOption.Identity]
  public Date DateCreated { get; set; }

  [DatabaseGeneratedOption.Identity]
  public Date DateModified { get; set; }

}

      

Please provide the exact steps to set up the DB to handle transaction metadata, for example what should be set in the model and if there are any actions in the DB context configurator. I was looking for something like "Everything You Need to Know About ASP.NET MVC Data Processing", but couldn't really touch that aspect.

Thanks in advance.

+3


source to share


2 answers


I'll think about it in terms of Entity-Framework.

You basically need to do the following:

1- I will define an interface like the ITrackable interface and make my models implement that interface if these models need to keep track of the DateCreated and DateModified characteristics.

2- Somehow your model knows if it is an added / modified entity, because it will determine which property to set (both for the added entity and just DateModified for the changed entities).

3- Using your DbContext in Entity-Framework, add an extension method that you need to call when you try to save your entities via SaveChanges or SaveChangesAsync, and this method will loop through the tracked entities and set the DateCreated and DateModified properties according to the entity. state.

So your model will look like this:

public class Person : IdentityUser, ITrackable
{

    [Required]
    public string Name { get; set; }

    public Date DateOfBirth { get; set; }

    public string Address { get; set; }

    public DateTime DateCreated { get; set; }

    public DateTime DateModified { get; set; }
}

      



Where ITrackable looks like

public interface ITrackable
{
    public DateTime DateCreated { get; set; }

    public DateTime DateModified { get; set; }
}

      

and the extension method would be something like this:

internal static class ContextHelper
{
    internal static void SyncObjectsStatePreCommit(this DbContext dbContext)
    {
        foreach (var dbEntityEntry in dbContext.ChangeTracker.Entries())
        {

            // do any other stuff you want.
            // ..
            // ..

            // work with ITrackable entities
            var trackableObject = dbEntityEntry.Entity as ITrackable;

            // we need to set/update trackable properties
            if (trackableObject == null)
            {
                continue;
            }

            var dateTime = DateTime.Now;

            // set createddate only for added entities
            if (entityState.ObjectState == ObjectState.Added)
            {
                trackableObject.CreatedDate = dateTime;
            }

            // set LastUpdatedDate for any case other than Unchanged
            if (entityState.ObjectState != ObjectState.Unchanged)
            {
                trackableObject.ModifiedDate = dateTime;
            }
        }
    }
}

      

Now, in your dbContext Save method, for example, you need to call this method to set all these properties.

public override Task<int> SaveChangesAsync()
{
    this.SyncObjectsStatePreCommit();
    return base.SaveChangesAsync();
}

      

Hope this helps.

+3


source


I found the above answer a little confusing, however I think a more direct solution would be to override the method SaveChanges

as described in this blog

This solution also uses an interface ITrackable

, and on startup, SaveChanges

it checks if this implements Entity

that interface:



public override System.Threading.Tasks.Task<int> SaveChangesAsync()
{
    foreach (var auditableEntity in ChangeTracker.Entries<ITrackableEntity>())
    {
        if (auditableEntity.State == EntityState.Added ||
            auditableEntity.State == EntityState.Modified)
        {
            // implementation may change based on the useage scenario, this
            // sample is for forma authentication.
            string currentUser = HttpContext.Current.User.Identity.GetUserId();
            DateTime currentDate = SiteHelper.GetCurrentDate();

            // modify updated date and updated by column for 
            // adds of updates.
            auditableEntity.Entity.ModifiedDateTime = currentDate;
            auditableEntity.Entity.ModifiedUserId = currentUser;

            // pupulate created date and created by columns for
            // newly added record.
            if (auditableEntity.State == EntityState.Added)
            {
                auditableEntity.Entity.CreatedDateTime = currentDate;
                auditableEntity.Entity.CreatedUserId = currentUser;
            }
            else
            {
                // we also want to make sure that code is not inadvertly
                // modifying created date and created by columns 
                auditableEntity.Property(p => p.CreatedDateTime).IsModified = false;
                auditableEntity.Property(p => p.CreatedUserId).IsModified = false;
            }
        }
    }
    return base.SaveChangesAsync();
}

      

0


source







All Articles