I am trying to figure out how to keep an object useable between client sessions in DB4O. From what I understand, once a client session is closed, the object no longer resides in any cache and despite the fact that I have a valid UUID, I cannot call Store on it without causing a duplicate to be inserted. I searched for a way to manually re-add it to the cache but there is no such mechanism. Re-retrieving it will force me to copy over all the values from the now useless object.
Here's the above paragraph in code:
Person person = new Person() { FirstName = "Howdoyu", LastName = "Du" };
Db4oUUID uuid;
// Store the new person in one session
using (IObjectContainer client = server.OpenClient())
{
client.Store(person);
uuid = client.Ext().GetObjectInfo(person).GetUUID();
}
// Guy changed his name, it happens
person.FirstName = "Charlie";
using (var client = server.OpenClient())
{
// TODO: MISSING SOME WAY TO RE-USE UUID HERE
client.Store(person); // will create a new person, named charlie, instead of changing Mr. Du's first name
}
The latest version of Eloquera supports these scenarios, either through an [ID] attribute or via Store(uid, object).
Any thoughts?
Okay, Gamlor's response about the db4o IExtContainer.Bind() method pointed me to the solution. Please note that this solution is only valid in very specific situations where access to the DB is tightly controlled, and no external queries can retrieve object instances.
Warning: This solution is dangerous. It can fill your database with all kinds of duplicates and junk objects, because it replaces the object and doesn't update its values, therefore breaking any references to it. Click here for a complete explanation.
UPDATE: Even in tightly controlled scenarios, this can cause endless headaches (like the one I'm having now) for anything other than a flat object with value type properties only (string, int, etc.). Unless you can design your code to retrieve, edit and save objects in a single db4o connection, then I recommend not to use db4o at all.
Person person = new Person() { FirstName = "Charles", LastName = "The Second" };
Db4oUUID uuid;
using (IObjectContainer client = server.OpenClient())
{
// Store the new object for the first time
client.Store(person);
// Keep the UUID for later use
uuid = client.Ext().GetObjectInfo(person).GetUUID();
}
// Guy changed his name, it happens
person.FirstName = "Lil' Charlie";
using (var client = server.OpenClient())
{
// Get a reference only (not data) to the stored object (server round trip, but lightweight)
Person inactiveReference = (Person) client.Ext().GetByUUID(uuid);
// Get the temp ID for this object within this client session
long tempID = client.Ext().GetID(inactiveReference);
// Replace the object the temp ID points to
client.Ext().Bind(person, tempID);
// Replace the stored object
client.Store(person);
}