locked
Cache RRS feed

  • Question

  • Hello,

    When we use a navigation property, we only use the cache (it's why we have Load method or Include on request).

    My question is, how can I request my cache directly without doing a SQL request?

    Indeed, if I execute twice the same query on context.MyEntity, I have two generated SQL request.

    When we did it first, data are in cache, so how can I do for request my cache and not my data base in second LINQ request?

    Thanks

    Matthieu

    Friday, January 11, 2008 10:55 AM

Answers

  • Unfortunately there is no built-in mechanism to accomplish what you are after.  The entity framework makes a strong distinction between three different things that you are interacting with:

     

    1) EntityCollections and EntityReferences which make up a graph of related objects.  When you iterate over one of these collections it is just an in memory collection and as you have observed looks something like a cache.

     

    2) The ObjectStateManager which looks something like a cache but really has a different purpose--it maintains information about entities for the purposes of change tracking and identitiy resolution but not as a target for running local queries.  As such it doesn't expose the information in a forum suitable for querying locally.  You can get access to the local data by retrieving a list of ObjectStateEntry's, but this isn't really what you are looking for.

     

    3) ObjectQuery's which represent the query you want to perform and can be enumerated in order to execute the query but will always run the query remotely.  The ObjectContext which codegen will create for you has ObjectQuery properties for each of the entitysets so that you can easily get to some interesting queries, but as you have observed they will always run against the database rather than over some local cache--because hte EF doesn't relaly have such a cache.

     

    So, if you need this capability, you have a couple of options.  Probably the best option is just to create your own cache mechanism.  This could be done fairly easily by adding a set of properties to the context partial class which could be as simple as List or something.  You could then do an initial load of these lists by executing queries.

     

    Another choice would be to use linq to objects to query the ObjectStateManager and transform the ObjectStateEntries into the entities you want to return.  This is nice because it doesn't involve maintaining a separate list, but it's much less efficient since it has to query over everything in the ObjectStateManager each time--the previous solution really only has to store a list of references to the entities so it's not that much overhead.  In any case, if you want to try this, your query might look something like this:

     

    Code Block

    from stateEntry in context.ObjectStateMnager

    .GetObjectStateEntries(EntityState.Added|EntityState.Modified|EntityState.UnChanged)

    where (stateEntry.IsRelationship == false) && (stateEntry.EntityKey.EntitySetName == "MyEntitySet")

    select stateEntry.Entity

     

    This would return all the entities that have been loaded into the context which are part of MyEntitySet.  You could then further refine this query with whatever predicate, projection, etc. you need by composing another linq query on top of it.

     

    - Danny

     

    Friday, January 11, 2008 4:55 PM