Db4o loads each object into reference cache only once in the session, thus ensuring that independently of the way of retrieving, you will always get a reference to the same object. This concept certainly makes things clearer, but in some cases you will want to operate on the copy of an object.
Typical usecases can be:
Db4o helps you with these tasks providing the following method:
c#: IExtObjectContainer.PeekPersisted(object, depth, committed)
VB: IExtObjectContainer.PeekPersisted(object, depth, committed)
This method creates a copy of a database object in memory instantiating its members up to depth parameter value. The object has no connection to the database.
Committed parameter defines whether committed or set values are to be returned. Let's see how you can use it.
We will use 2 threads measuring temperature independently in different parts of the car: somewhere in the cabin (getCabinTemperature) and on the conditioner unit (getConditionerTemperature).After some period of time the average measured value will be written to the database.
PeekPersistedExample.cs: MeasureCarTemperature private static void MeasureCarTemperature() { SetObjects(); IObjectContainer db = Db4oFactory.OpenFile(Db4oFileName); try { IObjectSet result = db.QueryByExample(typeof(Car)); if (result.Size() > 0) { Car car = (Car)result[0]; Car car1 = (Car)db.Ext().PeekPersisted(car, 5, true); Change1 ch1 = new Change1(); ch1.Init(car1); Car car2 = (Car)db.Ext().PeekPersisted(car, 5, true); Change2 ch2 = new Change2(); ch2.Init(car2); Thread.Sleep(300); // We can work on the database object at the same time car.Model = "BMW M3Coupe"; db.Store(car); ch1.Stop(); ch2.Stop(); System.Console.WriteLine("car1 saved to the database: " + db.Ext().IsStored(car1)); System.Console.WriteLine("car2 saved to the database: " + db.Ext().IsStored(car1)); int temperature = (int)((car1.Temperature + car2.Temperature)/2); car.Temperature = temperature; db.Store(car); } } finally { db.Close(); } �heckCar(); }
PeekPersistedExample.vb: MeasureCarTemperature Private Shared Sub MeasureCarTemperature() SetObjects() Dim db As IObjectContainer = Db4oFactory.OpenFile(Db4oFileName) Try Dim result As IObjectSet = db.QueryByExample(GetType(Car)) If result.Size() > 0 Then Dim car As Car = CType(result(0), Car) Dim car1 As Car = CType(db.Ext().PeekPersisted(car, 5, True), Car) Dim ch1 As Change1 = New Change1() ch1.Init(car1) Dim car2 As Car = CType(db.Ext().PeekPersisted(car, 5, True), Car) Dim ch2 As Change2 = New Change2() ch2.Init(car2) Thread.Sleep(300) ' We can work on the database object at the same time car.Model = "BMW M3Coupe" db.Store(car) ch1.Kill() ch2.Kill() System.Console.WriteLine("car1 saved to the database: " _ + db.Ext().IsStored(car1).ToString()) System.Console.WriteLine("car2 saved to the database: " _ + db.Ext().IsStored(car1).ToString()) Dim temperature As Integer = CType(((car1.Temperature _ + car2.Temperature) / 2), Integer) car.Temperature = temperature db.Store(car) End If Finally db.Close() End Try CheckCar() End Sub
peekPersisted method gives you an easy way to work with database objects' clones. Remember that these clones are totally disconnected from the database. If you will try to save such object you will get a new object in the database.
Download example code: