Master
Master

Reputation: 2153

How to deal with modified entity records

At the moment to check for changes with my entity framework object, I check in the database and I go through each object and compare the properties with the updated, if they are updated then my date modified will be updated as well.

I find that it's getting very lengthy in code and was wondering if there's a cleaner way to check for changes using entity framework. I was thinking maybe using deepcopy with a object comparison and compare something like below. But I would have to set each of my tables to be serialized and I don't know if that's a good thing.

if (Equals(oldentity, newentity))
{
    newentity.ModifiedDate = DateTime.Now
}

My current method of tracking changes

if (oldentity.firstname != newentity.firstname || oldentity.lastname != newentity.lastname)
{
    newentity.ModifiedDate = DateTime.Now
}

The if statement is a snippet, my entity has many properties so it gets lengthy...

Upvotes: 3

Views: 917

Answers (3)

David Sherret
David Sherret

Reputation: 106620

You can give your entity an interface with CreatedDate and ModifiedDate properties:

public interface ITrackedEntity
{
    DateTime CreatedDate    { get; set; }
    DateTime ModifiedDate   { get; set; }
}

Then override SaveChanges and SaveChangesAsync in the DBContext to handle updating the properties for added and modified entities automatically:

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

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

private void UpdateTrackedEntities()
{
    var entities = ChangeTracker.Entries().Where(x => x.Entity is ITrackedEntity && (x.State == EntityState.Added || x.State == EntityState.Modified));

    foreach (var entity in entities)
    {
        if (entity.State == EntityState.Added)
        {
            ((ITrackedEntity)entity.Entity).CreatedDate = DateTime.UtcNow;
        }

        ((ITrackedEntity)entity.Entity).ModifiedDate = DateTime.UtcNow;
    }
}

Makes things a lot simpler.

Upvotes: 1

Rafael Merlin
Rafael Merlin

Reputation: 2757

Entity Framework has a ChangeTracker in DbContext.

I for example have a override of my context's SaveChanges() and it is able to get all the changes made in my entities.

public override int SaveChanges()
{
    ChangeTracker.DetectChanges();
    var addedEntities = ChangeTracker.Entries().Where(x => x.State == EntityState.Added).ToList();
    var modifiedEntities = ChangeTracker.Entries().Where(x => x.State == EntityState.Modified).ToList();
    var deletedEntities = ChangeTracker.Entries().Where(x => x.State == EntityState.Deleted).ToList();

    //Save info generating the ids
    var ret = base.SaveChanges();

    //Generate Logs logic
    ...

    return ret;
}

ChangeTracker also accepts an entity as parameter if you want to check a just a single entity for changes.

More info on ChangeTracker (https://msdn.microsoft.com/en-us/library/system.data.entity.infrastructure.dbchangetracker(v=vs.113).aspx)

Upvotes: 0

Dario Griffo
Dario Griffo

Reputation: 4274

You can try something like

public bool HasUnsavedChanges(MyObject oldentity)
{
    return (YourObjectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Modified).Any(x=>x.Id == oldentity.Id));
}

Upvotes: 0

Related Questions