Reputation: 1926
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
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
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
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