Persistate

The session cache

Hide Navigation Pane

The session cache

Previous topic Next topic No directory for this topic  

The session cache

Previous topic Next topic Topic directory requires JavaScript JavaScript is required for the print function Mail us feedback on this topic!  

There are two mechanisms in Persistate which could be referred to as caching.  The first is what happens when you access a member property with an object class, whether it is scalar or a collection.  The object(s) accessed by that property are stored in a private field, which initially contains just a Reference or an empty collection.  When you access the property for the first time, Persistate replaces these with the appropriate retrieved object(s).  When you access the property subsequently, Persistate does not need to retrieve the object(s) again, since they are “cached” in the private field.

The session cache in Persistate, however, is quite different and independent of any particular object instance or property.  The first thing to be said about the session cache is that it works only on object classes in categories which have the use cache function, and the remainder of this discussion assumes this.  All of the standard class categories except Transitory and Volatile have this function.  See Class Category Definition for details.

The cache works slightly differently for scalar objects than for collections.  Here’s an example which contains places where both scenarios are possible.

Lend theLend;
Author theAuthor;
foreach (StockCopy copy in selectedBook.StockCopies) {
   if (copy.LendStatus == LendStatus.OnLoan) {
      theAuthor = selectedBook.Author;  // Cache could supply the stable author.
      theLend = copy.Lend;              // But not the transitory lend 
      
   }
}

There are several places here where the cache may have been involved.  For example, the collection access selectedBook.StockCopies may have involved it, and the selectedBook.Author access may have too.  However, the copy.Lend certainly will not have, since Lend objects are transitory.

For single object accesses, it’s quite straightforward, and works the same whether or not the accessed member is associated.  When you access the property, say selectedBook.Author, if the accessed author object is already in the private field, then as stated above, it is simply returned.  If not, then Persistate checks to see whether it is in the  session cache.  If it’s there, then Persistate gets it from the cache without any database access, installs it in the private field and returns it.  If the author isn’t there, then Persistate retrieves it from its database, installs it in the cache and the private field, and returns it.

For collection accesses, the situation is more complex, say for example in the selectedBook.StockCopies access.  When Persistate first retrieves the selectedBook object, the private field containing its StockCopies collection is empty.  The first time you access the collection therefore, Persistate must always retrieve the necessary objects from persistent storage.  On subsequent accesses, the collection exists, and Persistate returns it from the private field immediately.

As Persistate retrieves objects for a collection from persistent storage, it checks each one to see if it’s already in the cache.  If it isn’t, then Persistate puts it in, and also into the collection.  If it is in the cache, then Persistate doesn’t create a new object, but updates the cached object with the new values, unless the object has been modified.  In this latter case, the object’s modified flag will be set (see Modifying objects) and it is left as it is.  In all cases, however, Persistate puts the object into the collection.

This of course means that the modified object in the collection may be out of date compared with the most recent version in the database.  However, this is always possible in a scheme where optimistic concurrency is being used, and the problem will be raised at the next commit.

All of this means that all objects in memory having a class category with the use cache function are in the cache, and there are no duplicates.  The actual parent to child reference to an object, and all associated references to the same object will always access the same physical object in memory.  An object can be accessed by any number of single member associations, and be in any number of collections.

The implication of this is an important feature of Persistate and should inform how you program with persistent objects.   The persistent object graph (including associations) as it is built up in memory, mirrors the topology of the persistent object graph in persistent storage.

This applies to use cache objects only, but other objects are called transitory for a reason - they are usually associated with a point in time, are handled in one operation, and then are gone.  So the session cache builds up this graph of stable (etc) objects in memory, and Persistate ensures that whenever you access one, you always get the same instance.  Around this stable structure, the transitory objects flit past as they are dealt with one by one, and are gone.