Last time, when an identity map of the Deiphobus was described, one user entity of was asked about several times. We already know, that the same object was returned, but what about hitting the Cassandra DB? Consider the following code:
var user = session.Load<IUser>(5);
// some other loads and operations
var model = user.Login; // here goes db hit!
As you can see, the database is not hit till one of the properties is queried. It’s default and only mode of loading entities with Deiphobus. Is allows a great reduction of db calls, if your code is structured in a right way (query for data first, then operate). The question is, what if a user holds a few massive, in terms of bytes transported, properties. Will of them will be loaded at once, even if they’re unneeded? The answer will be revealed in a very next post.
Another feature of my mapper for Cassandra database, is the first level cache, commonly known as the identity map. Consider loading an entity of a user type only for displaying its login in the page header. Next, you’d like to get the same property to display it in several places across the page (for instance an author of a posts). I assume, that you use DI and your app creates only one session object per web request, injecting it in all the needed places. Consider the following code:
var user1 = session.Load<IUser>(5);
var user2 = session.Load<IUser>(5);
var user3 = session.Load<IUser>(5);
Now try to ReferenceEquals all the returned instances. Yes, that’s the same object! It means that there will be no problems with dirty tracking (what instance should I persist?). Also once an user is loaded with a session object, it can be re-retrieved without db hits. Isn’t it nice?
You can find a very nice description of Unit of Work in here. It describes a mythological artifact, which can understand what you’re doing with object retrieved from a database and allows you easily persist the whole state back to the database. Typically, clients for NoSQL databases do not provide this high abstraction of the persistence. Deiphobus makes a difference, providing a well known from other object mappers, the mighty unit of work, called Session. Below you can find how simple example of the session usage is:
// sessionFactory created earlier from a configuration
using (var s = sessionFactory.Open())
// entity creation makes it tracked, the state will be saved at s.Flush();
var user = s.Create<IUser>(t =>
t.Email = "Cassandra@cassandra.org";
t.AllowMarketingEmails = true;
var secret = s.Create<IPersonalInfo>(t =>
t.Type = PersonalInfoType.SecretFact;
t.Body = "I dislike SQL paradigm";
var quote = s.Create<IPersonalInfo>(t =>
t.Type = PersonalInfoType.Quote;
t.Body = "To be SQL or not to be";
// Flush to persist all changes at once! Dirty checks, etc. are handled without your coding!
It is simple and not dealing with checking what should be saved. Just create a session and call Flush when you want your changes be persisted. Of course it isn’t transactional as the database Cassandra isn’t, but still, it puts a nice layer over the standard Thrift protocol.