Embedded

From the API side, there's no real difference between transactions executing concurrently within the same VM and transactions executed against a remote server. To use concurrent transactions within a single VM, we just open a db4o server on our database file, directing it to run on port 0, thereby declaring that no networking will take place.

ClientServerExample.cs: AccessLocalServer
01public static void AccessLocalServer() 02 { 03 IObjectServer server = Db4oFactory.OpenServer(YapFileName, 0); 04 try 05 { 06 IObjectContainer client = server.OpenClient(); 07 // Do something with this client, or open more clients 08 client.Close(); 09 } 10 finally 11 { 12 server.Close(); 13 } 14 }

ClientServerExample.vb: AccessLocalServer
01Public Shared Sub AccessLocalServer() 02 Dim server As IObjectServer = Db4oFactory.OpenServer(YapFileName, 0) 03 Try 04 Dim client As IObjectContainer = server.OpenClient() 05 ' Do something with this client, or open more clients 06 client.Close() 07 Finally 08 server.Close() 09 End Try 10 End Sub

Again, we will delegate opening and closing the server to our environment to focus on client interactions.

ClientServerExample.cs: QueryLocalServer
1public static void QueryLocalServer(IObjectServer server) 2 { 3 IObjectContainer client = server.OpenClient(); 4 ListResult(client.Get(new Car(null))); 5 client.Close(); 6 }

ClientServerExample.vb: QueryLocalServer
1Public Shared Sub QueryLocalServer(ByVal server As IObjectServer) 2 Dim client As IObjectContainer = server.OpenClient() 3 ListResult(client.[Get](New Car(Nothing))) 4 client.Close() 5 End Sub

The transaction level in db4o is read committed. However, each client container maintains its own weak reference cache of already known objects. To make all changes committed by other clients immediately, we have to explicitly refresh known objects from the server. We will delegate this task to a specialized version of our listResult() method.

ClientServerExample.cs: ListRefreshedResult
1public static void ListRefreshedResult(IObjectContainer container, IObjectSet items, int depth) 2 { 3 System.Console.WriteLine(items.Count); 4 foreach (object item in items) 5 { 6 container.Ext().Refresh(item, depth); 7 System.Console.WriteLine(item); 8 } 9 }

ClientServerExample.vb: ListRefreshedResult
1Public Shared Sub ListRefreshedResult(ByVal container As IObjectContainer, ByVal items As IObjectSet, ByVal depth As Integer) 2 Console.WriteLine(items.Count) 3 For Each item As Object In items 4 container.Ext().Refresh(item, depth) 5 Console.WriteLine(item) 6 Next 7 End Sub

ClientServerExample.cs: DemonstrateLocalReadCommitted
01public static void DemonstrateLocalReadCommitted(IObjectServer server) 02 { 03 IObjectContainer client1 =server.OpenClient(); 04 IObjectContainer client2 =server.OpenClient(); 05 Pilot pilot = new Pilot("David Coulthard", 98); 06 IObjectSet result = client1.Get(new Car("BMW")); 07 Car car = (Car)result.Next(); 08 car.Pilot = pilot; 09 client1.Set(car); 10 ListResult(client1.Get(new Car(null))); 11 ListResult(client2.Get(new Car(null))); 12 client1.Commit(); 13 ListResult(client1.Get(typeof(Car))); 14 ListRefreshedResult(client2, client2.Get(typeof(Car)), 2); 15 client1.Close(); 16 client2.Close(); 17 }

ClientServerExample.vb: DemonstrateLocalReadCommitted
01Public Shared Sub DemonstrateLocalReadCommitted(ByVal server As IObjectServer) 02 Dim client1 As IObjectContainer = server.OpenClient() 03 Dim client2 As IObjectContainer = server.OpenClient() 04 Dim pilot As Pilot = New Pilot("David Coulthard", 98) 05 Dim result As IObjectSet = client1.[Get](New Car("BMW")) 06 Dim car As Car = DirectCast(result.[Next](), Car) 07 car.Pilot = pilot 08 client1.[Set](car) 09 ListResult(client1.[Get](New Car(Nothing))) 10 ListResult(client2.[Get](New Car(Nothing))) 11 client1.Commit() 12 ListResult(client1.[Get](GetType(Car))) 13 ListRefreshedResult(client2, client2.[Get](GetType(Car)), 2) 14 client1.Close() 15 client2.Close() 16 End Sub

Simple rollbacks just work as you might expect now.

ClientServerExample.cs: DemonstrateLocalRollback
01public static void DemonstrateLocalRollback(IObjectServer server) 02 { 03 IObjectContainer client1 = server.OpenClient(); 04 IObjectContainer client2 = server.OpenClient(); 05 IObjectSet result = client1.Get(new Car("BMW")); 06 Car car = (Car)result.Next(); 07 car.Pilot = new Pilot("Someone else", 0); 08 client1.Set(car); 09 ListResult(client1.Get(new Car(null))); 10 ListResult(client2.Get(new Car(null))); 11 client1.Rollback(); 12 client1.Ext().Refresh(car, 2); 13 ListResult(client1.Get(new Car(null))); 14 ListResult(client2.Get(new Car(null))); 15 client1.Close(); 16 client2.Close(); 17 }

ClientServerExample.vb: DemonstrateLocalRollback
01Public Shared Sub DemonstrateLocalRollback(ByVal server As IObjectServer) 02 Dim client1 As IObjectContainer = server.OpenClient() 03 Dim client2 As IObjectContainer = server.OpenClient() 04 Dim result As IObjectSet = client1.[Get](New Car("BMW")) 05 Dim car As Car = DirectCast(result.[Next](), Car) 06 car.Pilot = New Pilot("Someone else", 0) 07 client1.[Set](car) 08 ListResult(client1.[Get](New Car(Nothing))) 09 ListResult(client2.[Get](New Car(Nothing))) 10 client1.Rollback() 11 client1.Ext().Refresh(car, 2) 12 ListResult(client1.[Get](New Car(Nothing))) 13 ListResult(client2.[Get](New Car(Nothing))) 14 client1.Close() 15 client2.Close() 16 End Sub