When you query using Entity Framework, entities got are cached by default. Then, by default, if you query again and if you get some entities you already have in the EF cache, EF returns the cached instance.
With Entity Framework, there are 4 querying cache options:
Imagine the following scenario:
These options will change the e1 state after the second query.
This is the default option. With it, e1 doesn’t change from the first to the second query.
With this option, e1.P1 doesn’t change but P1 property is marked as changed. So, if User1 save changes, User2 changes will be erased.
Note that there are two different options for MergeOption.PreserveChanges with EF but we don’t take care here.
With this option, User1 get the same e1 instance than he got with the first query but e1.P1 is updated to value set by User2.
With this option, EF doesn’t use cache and we get new instances anytime we querying DB.
How to apply this option using EF?
It is not so easy. There is no way to apply it in general on the context. We have to apply it in each query.
With ObjectQuery, we have a MergeOption property that can be used to apply the option we want to.
Using queries from ObjectSet, we have to cast our query into ObjectQuery and then we can change the MergeOption.
Note that EF5 adds an AsNoTracking method that makes NoTracking usage easier.
Also note that, using DbSet, for PreserveChanges and OverwriteChanges you have to get ObjectSet from ObjectContext got using IObjectContextAdapter on your DbContext to be able to use it.
How to apply this option with WAQS?
You have two ways to do it:
- You have a MergeOption property on WAQS client context that will be used by default
- Execute method has a mergeOption optional parameter.
So you can use this code for example:
var customers = await _context.Customers.AsAsyncQueryable().ExecuteAsync(MergeOption.OverwriteChanges);
What about partial entity loading and With?
With current version, WAQS client context does not have a way to know which properties are loaded or not. So, if you load entities partially (to show a list for example) and if you want to load one fully (if you want to see its detail for example) in the same context and with any MergeOption except NoTracking, you can use OverwriteChanges.
For calculated properties load using a With, WAQS knows which ones were loaded. So if you use a With on a property you didn’t load, this property will be set for whatever MergeOption and, if it is already load, it will be erased only using OverwriteChanges.