Introduction
I previously wrote an article about how to discard changes of DbContext / ObjectContext in Entity Framework 6.0 without disposing of DbContext / ObjectContext. But this will discard all changes at the context level. Now I want to only discard some properties. Entity Framework is now able to reject changes to an individual property.
The Entity Framework maintains two values for each property of the tracked entity, current value and original value. For both names suggest theirself, the current value is the current value of the property and the original value is the value of the property when the entity was queried from the data source or attached to the context.
The property is marked as modified if the DetectChanges method determines that the property's current value is different from the original value (the value it had when the entity was queried or the entity was attached to the context). When we set the state of an entity to modified, then all the properties are marked as modified.
Properties are marked as modified will be important because these values will be sent to the database when the SaveChanges method of the context is called.
Checking whether a property is marked as modified
DbPropertyEntry has a property called "IsModified", it gets or sets a value indicating whether the value of this property has been modified from its original value.
- bool isCodeChanged = context.Entry(data).Property(p => p.Code).IsModified;
We can also set this property to true or false. The following code forces the property value sent to the database even if it has not changed from its original value.
- context.Entry(data).Property(p => p.Code).IsModified = true;
Example
Suppose I have the following code that has modified the code property of the “Employee” entity.
- static void Main(string[] args)
- {
- using (SQLLogging.Model.Model context = new SQLLogging.Model.Model())
- {
- var data = context.Employees.Where(p => p.Id == 1).FirstOrDefault();
- if (data != null)
- {
- data.Code = "ABB";
- }
- context.SaveChanges();
- }
- Console.ReadLine();
- }
To trace the query generated by Entity Framework, I must enable SQL logging.
- public partial class Model : DbContext
- {
- public Model() : base("name=EntityModel")
- {
- }
- ….
- ….
- ….
- protected override void OnModelCreating(DbModelBuilder modelBuilder)
- {
- Database.Log = Console.WriteLine;
- }
- }
Now run the code and check the output. Here the Entity Framework generates the update query.
OutputNow in the following code snippet I have forcefully reverted the change to the code property of the employee entity and checked the output.
- static void Main(string[] args)
- {
- using (SQLLogging.Model.Model context = new SQLLogging.Model.Model())
- {
- var data = context.Employees.Where(p => p.Id == 1).FirstOrDefault();
- if (data != null)
- {
- data.Code = "ABC";
-
- if (context.Entry(data).Property(p => p.Code).IsModified)
- {
-
- context.Entry(data).Property(p => p.Code).IsModified = false;
- }
- }
- context.SaveChanges();
- }
- Console.ReadLine();
- }
OutputWhen we tell Entity Framework that a property is no longer modified the context will do the following two things:
- Context will reset the current value to the original value. If the original value is not known then this will have no observable effect.
- Context will reset the modified flag.
Because the modified flag is reset this means that when SaveChanges is called the value of the property will not be sent to the database. Obviously this is a very small feature of Entity Framework (with .Net Framework 4.5) but it is useful.