Rollback And Cache


Suppose we have Car, Pilot and Id classes stored in the database. Car class is activatable, others are not. We will modify the car and rollback the transaction:

TPRollback.cs: ModifyAndRollback
01private static void ModifyAndRollback() 02 { 03 IObjectContainer container = Database(ConfigureTP()); 04 if (container != null) 05 { 06 try 07 { 08 // create a car 09 Car car = (Car)container.QueryByExample(new Car(null, null)) 10 [0]; 11 System.Console.WriteLine("Initial car: " + car + "(" 12 + container.Ext().GetID(car) + ")"); 13 car.Model = "Ferrari"; 14 car.Pilot = new Pilot("Michael Schumacher", 123); 15 container.Rollback(); 16 System.Console.WriteLine("Car after rollback: " + car + "(" 17 + container.Ext().GetID(car) + ")"); 18 } 19 finally 20 { 21 CloseDatabase(); 22 } 23 } 24 }
TPRollback.vb: ModifyAndRollback
01Private Shared Sub ModifyAndRollback() 02 Dim container As IObjectContainer = Database(ConfigureTP()) 03 If container IsNot Nothing Then 04 Try 05 ' create a car 06 Dim car As Car = DirectCast(container.QueryByExample(New Car(Nothing, Nothing))(0), Car) 07 System.Console.WriteLine("Initial car: " + car.ToString() + "(" + container.Ext().GetID(car).ToString() + ")") 08 car.Model = "Ferrari" 09 car.Pilot = New Pilot("Michael Schumacher", 123) 10 container.Rollback() 11 System.Console.WriteLine("Car after rollback: " + car.ToString() + "(" + container.Ext().GetID(car).ToString() + ")") 12 Finally 13 CloseDatabase() 14 End Try 15 End If 16 End Sub

If the transaction was going on normally (commit), we would have had the car modified in the database as it is supported by Transparent Persistence. However, as the transaction was rolled back - no modifications should be done to the database. The result that is printed to the screen is taken from the reference cache, so it will show modified objects. That is confusing and should be fixed:

TPRollback.cs: ModifyRollbackAndCheck
01private static void ModifyRollbackAndCheck() 02 { 03 IObjectContainer container = Database(ConfigureTP()); 04 if (container != null) 05 { 06 try 07 { 08 // create a car 09 Car car = (Car)container.QueryByExample(new Car(null, null)) 10 [0]; 11 Pilot pilot = car.Pilot; 12 System.Console.WriteLine("Initial car: " + car + "(" 13 + container.Ext().GetID(car) + ")"); 14 System.Console.WriteLine("Initial pilot: " + pilot + "(" 15 + container.Ext().GetID(pilot) + ")"); 16 car.Model = "Ferrari"; 17 car.ChangePilot("Michael Schumacher", 123); 18 container.Rollback(); 19 container.Deactivate(car, Int32.MaxValue); 20 System.Console.WriteLine("Car after rollback: " + car + "(" 21 + container.Ext().GetID(car) + ")"); 22 System.Console.WriteLine("Pilot after rollback: " + pilot + "(" 23 + container.Ext().GetID(pilot) + ")"); 24 } 25 finally 26 { 27 CloseDatabase(); 28 } 29 } 30 }
TPRollback.vb: ModifyRollbackAndCheck
01Private Shared Sub ModifyRollbackAndCheck() 02 Dim container As IObjectContainer = Database(ConfigureTP()) 03 If container IsNot Nothing Then 04 Try 05 ' create a car 06 Dim car As Car = DirectCast(container.QueryByExample(New Car(Nothing, Nothing))(0), Car) 07 Dim pilot As Pilot = car.Pilot 08 System.Console.WriteLine("Initial car: " + car.ToString() + "(" + container.Ext().GetID(car).ToString() + ")") 09 System.Console.WriteLine("Initial pilot: " + pilot.ToString() + "(" + container.Ext().GetID(pilot).ToString() + ")") 10 car.Model = "Ferrari" 11 car.ChangePilot("Michael Schumacher", 123) 12 container.Rollback() 13 container.Deactivate(car, Int32.MaxValue) 14 System.Console.WriteLine("Car after rollback: " + car.ToString() + "(" + container.Ext().GetID(car).ToString() + ")") 15 System.Console.WriteLine("Pilot after rollback: " + pilot.ToString() + "(" + container.Ext().GetID(pilot).ToString() + ")") 16 Finally 17 CloseDatabase() 18 End Try 19 End If 20 End Sub

Here we've added a deactivate call for the car object. This call is used to clear the reference cache and its action is reversed to activate.

We've used Integer.MAX_VALUE/Int32.MaxValue to deactivate car fields to the maximum possible depth. Thus we can be sure that all the car fields will be re-read from the database again (no outdated values from the reference cache), but the trade-off is that all child objects will be deactivated and read from the database too. You can see it on Pilot object. This behaviour is preserved for both activatable and non-activatable objects.