gunnerz
gunnerz

Reputation: 1926

Entity Framework Update check if the record has changed

I am updating a database table using EF.

Its a simple scenario in connected mode.

I get the row I want to update

var order = from o in Orders
        where o.ID = 1
        select o;

I then update the record as:

order.FirstName = "First";
order.LastName = "Last";
context.SaveChanges();

It works fine. EF checks if the field has changed and only updates the field if its a new value. I have enabled CDC on my SQL server to check that EF does not rewrite to the database if the value has not changed.

Now I want to put this check in my code for additional logic i.e. I want EF to tell me when the record was updated, and when it was not (because the value has not changed). Can anyone please tell if there is a way?

I do not want to manually check each field as I have a lot of fields to compare.

Thanks

Upvotes: 11

Views: 21671

Answers (3)

我零0七
我零0七

Reputation: 473

I create a extension like this:

/// <summary>
/// check entity is modified
/// <remarks>ignore<see cref="IUpdate"/>interface modified</remarks>
/// </summary>
/// <param name="context"></param>
/// <param name="logger"></param>
/// <returns></returns>
public static bool IsEntityModified(this DBContext context,ILogger logger=null)
{
    foreach (var e in context.ChangeTracker.Entries())
    {
        foreach (var propertyEntry in e.Properties)
        {
            if (propertyEntry.IsModified &&
                propertyEntry.OriginalValue?.ToString() != propertyEntry.CurrentValue?.ToString())
            {
                if (propertyEntry.Metadata.DeclaringEntityType.ClrType.IsAssignableTo(typeof(IUpdate)) &&
                    typeof(IUpdate).GetProperty(propertyEntry.Metadata.Name) != null)
                {
                    logger?.LogInformation(
                        "the property :{propertyName} in type:{declarType} is modified ,but is assignable to IUpdate ignore it",
                        propertyEntry.Metadata.Name, propertyEntry.Metadata.DeclaringEntityType.FullName());
                }
                else
                {
                    logger?.LogWarning(
                        "by property :{propertyName} in type:{declarType}  modified ,return ture",
                        propertyEntry.Metadata.Name, propertyEntry.Metadata.DeclaringEntityType.FullName());
                    return true;
                }
            }
        }
    }
    return false;
}

And my IUpdate interface just like this.When only update it,the extension will return false.

    public interface IUpdate
    {
         string UpdateUser { get; set; }
         DateTime? UpdateTime { get; set; }
    }

Upvotes: 0

gunnerz
gunnerz

Reputation: 1926

If anybody is interested, here is what I did. I created the following method to check if any field has changed before saving changes.

private Dictionary<Type, bool> IsEntityModified()
{
    Dictionary<Type, bool> entity = new Dictionary<Type, bool>();
    var items = _bentities.ObjectStateManager.GetObjectStateEntries(EntityState.Modified);
    foreach (ObjectStateEntry entry in items)
    {
        foreach (string propName in entry.GetModifiedProperties())
        {
            string oldsetterValue, newsetterValue = null;
            // Get orginal value 
            oldsetterValue = entry.OriginalValues[propName].ToString();
            // Get new value 
            newsetterValue = entry.CurrentValues[propName].ToString();

            if (oldsetterValue != newsetterValue)
            {
                entity.Add(entry.Entity.GetType(), true);
            }
        }
    }
    return entity;
}

Upvotes: 9

ooXei1sh
ooXei1sh

Reputation: 3539

I came across this question/answer when I was looking for something similar if not the same thing. I ended up using this approach which seems to work alright for me.

var order = from o in context.Orders
        where o.ID = 1
        select o;

order.FirstName = "First";
order.LastName = "Last";

if (context.Entry(order).State != EntityState.Unchanged)
{
    // order has changed ...
}

So posting what worked for me in case it might be helpful for others who come here looking for something similar.

Upvotes: 9

Related Questions