db4o: Activation- & Update-Depth

Activation is a very basic concept in db4o. In this post I’ll illustrate what it is, why it’s there and how you handle it.

(All posts of this series: the basics, activation, object-identity, transactions, persistent classes, single container concurrency, Queries in Java, C# 2.0, client-server concurrency, transparent persistence, adhoc query tools)

The Mysterious Null-Pointer

Let’s start with a mysterious exception! With the knowledge of the previous post we store some objects. This time a person has a property which refers to the person’s boss. We store six instances. Each person is the boss of another one.

var ceo = new Person("Julius", "Caesar");
var firstGeneral = new Person("NoIdea", "WhoCareus", ceo);
var secondGeneral = new Person("Master", "Chiefius", firstGeneral);
var captain = new Person("Biggest", "Halo-Geekius", secondGeneral);
var officer = new Person("Plus", "Nixus", captain);
var normalPerson = new Person("Mius", "Dius", officer);
container.Store(normalPerson);
 

Everything fine so far. Then we decide to write a little method which prints the initials “Mius Dius” and all its superiors. It runs fine until it should print the initials of “Julius Caesar”. There a NullReferenceException is thrown. Somehow all the properties of that person are null. But why?

 
var person = (from Person p in db
              where p.FirstName.Equals("Mius")
              select p).Single();
while (null != person)
{
    // on the last person 'Julius Caesar' properties are null, hence this will fail 
    Console.Out.WriteLine(
        string.Format("Persons initials {0}.{1}.", person.FirstName[0], person.SirName[0]));
    person = person.Boss;
}

Activation. What is it? Why is it there?

As seen above, all properties of “Julius Caesar” are empty. db4o simply hasn’t loaded the “Julius Caesar”-object from the database into memory yet. And there’s a good reason for that. db4o stores object-graphs. Assume you have stored a complex object-graph with thousands of objects. Now you load a single object from the database. Imagine db4o would ensure that all references to other objects are set properly. Then db4o would have to load your whole object-graph (this could be the whole database) into memory.

db4o without activation

db4o without activation 😉

 To avoid that, db4o introduces a concept called Activation. db4o loads only a part of the object-graph into memory. The fully loaded objects are ‘activated’. At the ‘edge’ of the the object-graph are object which are not activated yet. All properties of such objects are not set. To use such a object, you have to ‘activate’ it first. This will load the missing data from the database.

db4o with activation ;)

db4o with activation 😉

Dealing With Activation

By default db4o has an activation-depth of 5. That means that the retrieved object and all objects which can be reached over 4 references are activated. If you want more, you can activate an object anytime. You just pass the object and the activation-depth to IObjectContainer.Activate()

db.Activate(person,5);
db4o-activate

Its also possible to change the global default or change the activation-depth for a specific class.

A higher activation-depth makes it more pleasant to work. However it uses more memory and can have a negative impact on the performance. You have to experiment with it.

Get Rid Of The Activation-Pain

Well activation can be a pain in the ass. So, witty people came up with a solution: Transparent Activation. Basically this makes persisted objects aware of their activation-state. As soon as you access a property the first time the object activates itself. You can hand-code Transparent Activation by implementing interfaces or used byte-code-enhancers. I haven’t used Transparent Activation so far, so I can’t share any experience.

The Lost Update

So after all this complex activation stuff we update some objects.

person.SirName = "Cool-NewName";
person.Boss.SirName = "Cool-NewBoss";
db.Store(person);
 

Later we retrieve the same person and read the properties:

Console.Out.WriteLine(person.SirName);
Console.Out.WriteLine(person.Boss.SirName);

And the console output is this:

Cool-NewName
Nixus

Oh noes, the name-change on the boss is lost. Well you can thinks of the reason?

Update-Depth

Analogical to the activation-depth there is an update-depth in db4o. For similar reasons as the activation-depth. By default db4o simple doesn’t traverse the object-graph to look for changes. It only updates objects which was updated explicitly with IObjectContainer.Store(). (This applies only for updating. New objects are always stored completely).

Again you can change this setting globally, for a class or specify it on the Store()-call.

I’m Really To Lazy For All This Stuff

Well then you should try Transparent Persistance. Basically this is a way to make your object fully database-aware. You store the object once in the database. After that, all changes you make on the object are reflected in the database ‘by magic’. Again you can implement this manually or use byte-code-enhancers. And again, I haven’t tried it so far. 

Next time

You might wonder how the heck db4o identifies its objects. There are no explicit ids like you use in hibernate & co. Well I’ll explain that next time =)

Example-Source-Code: Person.cs, Program.cs

Tagged on: ,

3 thoughts on “db4o: Activation- & Update-Depth

  1. Pingback: db4o: Client-Server and Concurrency « Gamlor