The use of depth parameter in deactivate call from
the previous example directly affects performance: the
less is the depth the less objects will need to be re-read from the database
and the better the performance will be. Ideally we only want to deactivate the
objects that were changed in the rolled-back transaction. This can be done by
providing a special class for db4o configuration. This class should implement
RollbackStrategy/IRollbackStrategy interface and is configured as
part of Transparent Persistence support:
TPRollback.cs: RollbackDeactivateStrategy
private class RollbackDeactivateStrategy : IRollbackStrategy
{
public void Rollback(IObjectContainer container, Object obj)
{
container.Ext().Deactivate(obj);
}
}
TPRollback.cs: ConfigureTPForRollback
private static IConfiguration ConfigureTPForRollback()
{
IConfiguration configuration = Db4oFactory.NewConfiguration();
// add TP
support and rollback strategy
configuration.Add(new TransparentPersistenceSupport(
new RollbackDeactivateStrategy()));
return configuration;
}
TPRollback.vb: RollbackDeactivateStrategy
Private Class RollbackDeactivateStrategy
Implements IRollbackStrategy
Public Sub Rollback(ByVal container As IObjectContainer, _
ByVal obj As Object) _
Implements IRollbackStrategy.Rollback
container.Ext().Deactivate(obj)
End Sub
End Class
TPRollback.vb: ConfigureTPForRollback
Private Shared Function ConfigureTPForRollback() As IConfiguration
Dim configuration As IConfiguration = Db4oFactory.NewConfiguration()
' add TP support and rollback strategy
configuration.Add(New TransparentPersistenceSupport _
(New RollbackDeactivateStrategy()))
Return configuration
End Function
RollbackDeactivateStrategy#rollback method will be automatically called once per each modified object after the rollback. Thus you do not have to worry about deactivate depth anymore - all necessary deactivation will happen transparently preserving the best performance possible.
TPRollback.cs: ModifyWithRollbackStrategy
private static void ModifyWithRollbackStrategy()
{
IObjectContainer container = Database(ConfigureTPForRollback());
if (container != null)
{
try
{
// create a car
Car car = (Car)container.QueryByExample(new Car(null, null))
[0];
Pilot pilot = car.Pilot;
System.Console.WriteLine("Initial car: " + car + "("
+ container.Ext().GetID(car) + ")");
System.Console.WriteLine("Initial pilot: " + pilot + "("
+ container.Ext().GetID(pilot) + ")");
car.Model = "Ferrari";
car.ChangePilot("Michael Schumacher", 123);
container.Rollback();
System.Console.WriteLine("Car after rollback: " + car + "("
+ container.Ext().GetID(car) + ")");
System.Console.WriteLine("Pilot after rollback: " + pilot + "("
+ container.Ext().GetID(pilot) + ")");
}
finally
{
CloseDatabase();
}
}
}
TPRollback.vb: ModifyWithRollbackStrategy
Private Shared Sub ModifyWithRollbackStrategy()
Dim container As IObjectContainer = Database(ConfigureTPForRollback())
If container IsNot Nothing Then
Try
' create a car
Dim car As Car = DirectCast(container. _
QueryByExample(New Car(Nothing, Nothing))(0), Car)
Dim pilot As Pilot = car.Pilot
System.Console.WriteLine("Initial car: " + _
car.ToString() + "(" + container.Ext().GetID(car).ToString() + ")")
System.Console.WriteLine("Initial pilot: " + _
pilot.ToString() + "(" + _
container.Ext().GetID(pilot).ToString() + ")")
car.Model = "Ferrari"
car.ChangePilot("Michael Schumacher", 123)
container.Rollback()
System.Console.WriteLine("Car after rollback: " + _
car.ToString() + "(" + _
container.Ext().GetID(car).ToString() + ")")
System.Console.WriteLine("Pilot after rollback: " + _
pilot.ToString() + _
"(" + container.Ext().GetID(pilot).ToString() + ")")
Finally
CloseDatabase()
End Try
End If
End Sub
Note, that RollbackDeactivateStrategy only works for activatable objects. To see the different you can comment out Activatable implementation in Id class (id value will be preserved in the cache).
Download example code: