I have a single data context (created once), and I use it to get the same database record several times, for example, I get the same product record specifying the same product ID.
Each time I call, let’s say, context.Products.Single(p => p.ProdID == 1), context returns the same instance of the product entity, BUT queries the database each time, which is visible in SQL Server Profiler.
I check that it returns the same instance by modifying some properties between the calls. The next call returns the instance with the modified properties.
Why it queries database each time, and is there a way to avoid this?
You can use ObjectContext.GetObjectByKey (
DbSet<T>.FindforDbContext) to query for an entity by its key. This method will check if the object with the specified key is already attached to the context. If yes, it will return that object without querying the database. If it doesn’t exist in the context it runs a database query.LINQ queries generally query the database, no matter if the objects are already attached to the context or not. EF cannot know up front if the objects are attached or not because it doesn’t know the result of the query. Your LINQ query by key is an exception – theoretically – because EF could know if the query is necessary or not since it could check if the object with that key is already attached. But this exception is not handled as such – that’s why
GetObjectByKeyexists – and it queries the database like every other LINQ query.What happens with the query result is determined by the ObjectSet’s MergeOption. The default is
AppendOnlywhich means that the query result is thrown away if an object with the key is already attached to context. Nothing gets overwritten or refreshed by the query. Only if an object with the key doesn’t exist in the context an object from the query result is materialized and will be attached to the context. You can change this default behaviour by choosing anotherMergeOption.