LP13
LP13

Reputation: 34149

Implicitly set common properties in Entity Framework 6

My application is using EF6 database first approach. All the entities in the database have 2 common properties "CreatedDateTime" and "ModifiedDateTime".

Currently When i do SaveChanges() im explicitly setting these 2 properties based on if i am creating new entity or updating existing entity.

If its a new entity then set both properties else set only ModifiedDateTime property.

I wanted to know if there is a way to implicitly set these 2 properties on Save or update operation?

Update 1
I know i have to override Savechanges() method however the real issue here is SaveChanges needs to have access to these 2 properties. So i only see 2 options here:
1> Use reflection to find if entity has these properties and set it.
2> Modify default T4 generation so that it derives all entities with predefined interface. And this interface will have these 2 properties. SaveChanges() method can check if entity is derived from this interface and set the property.

I defiantly don't want to use option 1 using refection.

Is there any other way or has anyone done this before in DB first approach?

Upvotes: 1

Views: 307

Answers (1)

Stephen Reindl
Stephen Reindl

Reputation: 5829

Going with your second approach: Adjust your T4 files to include a reference to an interface (e.g. IChangeTrack):

public interface IChangeTrack
{
    /// <summary>
    /// When has this entry be created
    /// </summary>
    [Required]
    DateTime CreatedDateTime { get; set; }

    /// <summary>
    /// When has this entry been modified
    /// </summary>
    DateTime? ModifiedDateTime { get; set; }
}

Now overwrite your SaveChanges() routine by doing something like this:

/// <summary>
/// Enhance save changes to handle system fields.
/// </summary>
/// <returns></returns>
public override int SaveChanges()
{
    HandleChanges();
    int changes = base.SaveChanges();
    return changes;
}

public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken)
{
    HandleChanges();
    int changes = await base.SaveChangesAsync(cancellationToken);
    return changes;
}


private void HandleChanges()
{
    ChangeTracker.DetectChanges();
    var entries = ChangeTracker.Entries<IChangeTrack>();
    if (entries != null)
    {
        foreach (DbEntityEntry<IChangeTrack> entry in entries)
        {
            switch (entry.State)
            {
                case EntityState.Added:
                    entry.Entity.CreatedDateTime = DateTime.UtcNow
                    break;
                case EntityState.Modified:
                    entry.Entity.ModifiedDateTime = DateTime.UtcNow;
                    break;
            }
        }
    }
}

Upvotes: 4

Related Questions