Conflict Resolution

The most popular usage of replication callback events is conflict resolution. When an object was changed in both replicating databases you must have a strategy to decide, which value must be final. In the simplest case one of the databases is made "dominant" and the changes in this database always override other changes. The following example demonstrates this behavior:

 

 

EventsExample.cs: ConflictResolutionExample
01private static void ConflictResolutionExample() 02 { 03 Db4oFactory.Configure().GenerateUUIDs(ConfigScope.GLOBALLY); 04 Db4oFactory.Configure().GenerateVersionNumbers(ConfigScope.GLOBALLY); 05 // Open databases 06 IObjectContainer desktop = Db4oFactory.OpenFile("desktop.db4o"); 07 IObjectContainer handheld = Db4oFactory.OpenFile("handheld.db4o"); 08 09 Pilot pilot = new Pilot("Scott Felton", 200); 10 handheld.Set(pilot); 11 handheld.Commit(); 12 /* Clean the reference cache to make sure that objects in memory 13 * won't interfere 14 */ 15 handheld.Ext().Refresh(typeof(Pilot), System.Int32.MaxValue); 16 17 /* Replicate changes from handheld to desktop 18 * Note, that only objects replicated from one database to another will 19 * be treated as the same. If you will create an object and save it to both 20 * databases, dRS will count them as 2 different objects with identical 21 * fields. 22 */ 23 IReplicationSession replication = Db4objects.Drs.Replication.Begin(handheld, desktop); 24 IObjectSet changedObjects = replication.ProviderA().ObjectsChangedSinceLastReplication(); 25 while (changedObjects.HasNext()) 26 replication.Replicate(changedObjects.Next()); 27 replication.Commit(); 28 29 // change object on the handheld 30 pilot = (Pilot)handheld.Query(typeof(Pilot)).Next(); 31 pilot.Name = "S.Felton"; 32 handheld.Set(pilot); 33 handheld.Commit(); 34 35 // change object on the desktop 36 pilot = (Pilot)desktop.Query(typeof(Pilot)).Next(); 37 pilot.Name = "Scott"; 38 desktop.Set(pilot); 39 desktop.Commit(); 40 41 /* The replication will face a conflict: Pilot object was changed on the 42 * handheld and on the desktop. 43 * To resolve this conflict we will add an event handler, which makes 44 * desktop changes dominating. 45 */ 46 IReplicationEventListener listener = new ConflictReplicationEventListener(); 47 replication = Db4objects.Drs.Replication.Begin(handheld, desktop, listener); 48 49 //The state of the desktop after the replication should not change, as it dominates 50 changedObjects = replication.ProviderA().ObjectsChangedSinceLastReplication(); 51 while (changedObjects.HasNext()) 52 replication.Replicate(changedObjects.Next()); 53 54 //Commit 55 replication.Commit(); 56 replication.Close(); 57 58 // Check what we've got on the desktop 59 IObjectSet result = desktop.Query(typeof(Pilot)); 60 System.Console.WriteLine(result.Size()); 61 while (result.HasNext()) 62 { 63 System.Console.WriteLine(result.Next()); 64 } 65 handheld.Close(); 66 desktop.Close(); 67 68 File.Delete("handheld.db4o"); 69 File.Delete("desktop.db4o"); 70 71 }
EventsExample.cs: ConflictReplicationEventListener
01public class ConflictReplicationEventListener : Db4objects.Drs.IReplicationEventListener 02 { 03 public virtual void OnReplicate(Db4objects.Drs.IReplicationEvent e) 04 { 05 if (e.IsConflict()) 06 { 07 IObjectState chosenObjectState = e.StateInProviderB(); 08 e.OverrideWith(chosenObjectState); 09 } 10 } 11 }

 

EventsExample.vb: ConflictResolutionExample
01Private Shared Sub ConflictResolutionExample() 02 Db4oFactory.Configure().GenerateUUIDs(ConfigScope.GLOBALLY) 03 Db4oFactory.Configure().GenerateVersionNumbers(ConfigScope.GLOBALLY) 04 ' Open databases 05 Dim desktop As IObjectContainer = Db4oFactory.OpenFile("desktop.db4o") 06 Dim handheld As IObjectContainer = Db4oFactory.OpenFile("handheld.db4o") 07 08 Dim pilot As New Pilot("Scott Felton", 200) 09 handheld.[Set](pilot) 10 handheld.Commit() 11 ' Clean the reference cache to make sure that objects in memory 12 ' won't interfere 13 14 handheld.Ext().Refresh(GetType(Pilot), System.Int32.MaxValue) 15 16 ' Replicate changes from handheld to desktop 17 ' Note, that only objects replicated from one database to another will 18 ' be treated as the same. If you will create an object and save it to both 19 ' databases, dRS will count them as 2 different objects with identical 20 ' fields. 21 Dim replication As IReplicationSession = Db4objects.Drs.Replication.Begin(handheld, desktop) 22 Dim changedObjects As IObjectSet = replication.ProviderA().ObjectsChangedSinceLastReplication() 23 While changedObjects.HasNext() 24 replication.Replicate(changedObjects.Next()) 25 End While 26 replication.Commit() 27 28 ' change object on the handheld 29 pilot = DirectCast(handheld.Query(GetType(Pilot)).[Next](), Pilot) 30 pilot.Name = "S.Felton" 31 handheld.[Set](pilot) 32 handheld.Commit() 33 34 ' change object on the desktop 35 pilot = DirectCast(desktop.Query(GetType(Pilot)).[Next](), Pilot) 36 pilot.Name = "Scott" 37 desktop.[Set](pilot) 38 desktop.Commit() 39 40 ' The replication will face a conflict: Pilot object was changed on the 41 ' handheld and on the desktop. 42 ' To resolve this conflict we will add an event handler, which makes 43 ' desktop changes dominating. 44 Dim listener As IReplicationEventListener = New ConflictReplicationEventListener() 45 replication = Db4objects.Drs.Replication.Begin(handheld, desktop, listener) 46 47 'The state of the desktop after the replication should not change, as it dominates 48 changedObjects = replication.ProviderA().ObjectsChangedSinceLastReplication() 49 While changedObjects.HasNext() 50 replication.Replicate(changedObjects.[Next]()) 51 End While 52 53 'Commit 54 replication.Commit() 55 replication.Close() 56 57 ' Check what we've got on the desktop 58 Dim result As IObjectSet = desktop.Query(GetType(Pilot)) 59 System.Console.WriteLine(result.Size()) 60 While result.HasNext() 61 System.Console.WriteLine(result.[Next]()) 62 End While 63 handheld.Close() 64 desktop.Close() 65 66 File.Delete("handheld.db4o") 67 File.Delete("desktop.db4o") 68 69 End Sub
 

EventsExample.vb: ConflictReplicationEventListener
1Public Class ConflictReplicationEventListener 2 Implements Db4objects.Drs.IReplicationEventListener 3 Public Overridable Sub OnReplicate(ByVal e As Db4objects.Drs.IReplicationEvent) Implements Db4objects.Drs.IReplicationEventListener.OnReplicate 4 If e.IsConflict() Then 5 Dim chosenObjectState As IObjectState = e.StateInProviderB() 6 e.OverrideWith(chosenObjectState) 7 End If 8 End Sub 9 End Class