问题
Does creating DbContext per query in Asp.net make EF only read the data from its cache, or does it query DB for the whole sets every time? I know about metadata caching per AppDomain, but what about just the data?
Context: data acquisition and visualisation application with MVC4 + Web API frontend, wouldn't call that "high volume", but lots of queries return the same sets of data in some shorter time frame.
回答1:
Entity Framework doesn't have a data cache per AppDomain, only a cache per context instance.
If you create a new context per request or query you start with an empty cache and EF will fetch the data from the database.
Moreover, the term "cache per context instance" can be misleading as it doesn't mean that EF won't run queries to the database if the entities are already loaded in the context cache. The way how this cache works and how you can leverage it (or not) is the following:
Every LINQ-to-Entities query on a
DbSet<T>
or generally on anIQueryable<T>
will run a database query, no matter if the entities already exist in the context or not. But if an entity with the same key as a queried entity already exists in the context EF will throw the result of that query away and return the cached entity instance back to the caller.It does this check if the entity with the same key exists after it has run the query. (For complex queries - for example queries that contain an
Include
- it can't do this check before because it cannot know which entities and key values will be returned.)That's the default behaviour (
MergeOption
isAppendOnly
). You can change this behaviour toOverwriteChanges
and other options, I believe, but none of them will avoid that LINQ queries always issue database queries.For querying an entity just by its key you can use
GetObjectByKey
orFind
(withDbContext
) which will check first if the entity with that key is already cached in the context and then return this cached object. If not it will run a database query to load it.You can query EF's ChangeTracker, it's especially well supported with
DbContext
where you have access to the context cache via theDbSet<T>.Local
collection.The problem here is that there is no logic to query the database automatically if a query on
Local
does not return a result. You have to write this logic manually. The even bigger problem is that a query onLocal
is LINQ-to-Objects and not LINQ-to-Entities (Local
doesn't implementIQueryable<T>
, onlyIEnumerable<T>
), so you often have to rewrite your queries to act onLocal
- for example you can't useInclude
here, your can't use anyEntityFunctions
, you will get different behaviour for string comparisons regarding case sensitivity, etc., etc.
来源:https://stackoverflow.com/questions/17042697/does-ef-caches-entities-between-different-instances-of-dbcontext