Collection Example

In the previous example we reviewed how Transparent Persistence should be used with simple types. Let's now look how it is done with the collections.

In order to make collections TP Activatable you will need to use db4o-specific ArrayList4 collection. This collection implements .NET/Java collection interfaces, therefore it can be easily integrated with your code. The following class contains a collection of Pilot objects:

Team.cs
01/* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com */ 02using System.Collections.Generic; 03using System.Collections; 04 05using Db4objects.Db4o; 06using Db4objects.Db4o.Activation; 07using Db4objects.Db4o.TA; 08using Db4objects.Db4o.Collections; 09 10namespace Db4objects.Db4odoc.TPExample 11{ 12 public class Team : IActivatable 13 { 14 15 IList<Pilot> _pilots = new ArrayList4<Pilot>(); 16 17 string _name; 18 19 //TA Activator 20 [System.NonSerialized] 21 IActivator _activator; 22 23 24 // Bind the class to an object container 25 public void Bind(IActivator activator) 26 { 27 if (_activator == activator) 28 { 29 return; 30 } 31 if (activator != null && null != _activator) 32 { 33 throw new System.InvalidOperationException(); 34 } 35 _activator = activator; 36 } 37 38 // activate object fields 39 public void Activate(ActivationPurpose purpose) 40 { 41 if (_activator == null) return; 42 _activator.Activate(purpose); 43 } 44 45 public void AddPilot(Pilot pilot) 46 { 47 // activate before adding new pilots 48 Activate(ActivationPurpose.Read); 49 _pilots.Add(pilot); 50 } 51 52 public int Size() 53 { 54 // activate before returning 55 Activate(ActivationPurpose.Read); 56 return _pilots.Count; 57 } 58 // end Size 59 60 public void ListAllPilots() 61 { 62 // activate before printing the collection members 63 Activate(ActivationPurpose.Read); 64 foreach (Pilot pilot in _pilots) 65 { 66 System.Console.WriteLine(pilot); 67 } 68 } 69 70 public IList<Pilot> Pilots 71 { 72 get 73 { 74 Activate(ActivationPurpose.Read); 75 return _pilots; 76 } 77 } 78 // end Pilots 79 80 } 81}
Team.vb
01' Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com 02Imports System.Collections.Generic 03Imports Db4objects.Db4o 04Imports Db4objects.Db4o.Activation 05Imports Db4objects.Db4o.TA 06Imports Db4objects.Db4o.Collections 07 08 09Namespace Db4objects.Db4odoc.TPExample 10 11 Public Class Team 12 Implements IActivatable 13 14 Private _pilots As IList(Of Pilot) = New ArrayList4(Of Pilot) 15 Private _name As String 16 17 ' TA Activator 18 <Transient()> _ 19 Private _activator As IActivator 20 21 Public ReadOnly Property Pilots() As IList(Of Pilot) 22 Get 23 Activate(ActivationPurpose.Read) 24 Return _pilots 25 End Get 26 End Property 27 28 29 ' Bind the class to an object container 30 Public Sub Bind(ByVal activator As IActivator) Implements IActivatable.Bind 31 If _activator Is activator Then 32 Return 33 End If 34 If Not (activator Is Nothing Or _activator Is Nothing) Then 35 Throw New System.InvalidOperationException() 36 End If 37 _activator = activator 38 End Sub 39 40 ' activate object fields 41 Public Sub Activate(ByVal purpose As ActivationPurpose) Implements IActivatable.Activate 42 If _activator Is Nothing Then 43 Return 44 End If 45 _activator.Activate(ActivationPurpose.Read) 46 End Sub 47 48 Public Sub AddPilot(ByVal pilot As Pilot) 49 ' activate before adding new pilots 50 Activate(ActivationPurpose.Read) 51 _pilots.Add(pilot) 52 End Sub 53 54 Public Function Size() As Integer 55 ' activate before returning 56 Activate(ActivationPurpose.Read) 57 Return _pilots.Count 58 End Function 59 60 Public Sub ListAllPilots() 61 ' activate before printing the collection members 62 Activate(ActivationPurpose.Read) 63 Dim p As Pilot 64 For Each p In _pilots 65 System.Console.WriteLine(p) 66 Next 67 End Sub 68 69 End Class 70End Namespace

You can see that except for using ArrayList4, the implementation follows the same rules as in the previous simple example.

Its usage has no surprises as well:

TPCollectionExample.cs: StoreCollection
01private static void StoreCollection() 02 { 03 File.Delete(Db4oFileName); 04 IObjectContainer container = Database(ConfigureTP()); 05 if (container != null) 06 { 07 try 08 { 09 Team team = new Team(); 10 for (int i = 0; i < 10; i++) 11 { 12 team.AddPilot(new Pilot("Pilot #" + i)); 13 } 14 container.Set(team); 15 container.Commit(); 16 } 17 catch (Exception ex) 18 { 19 System.Console.WriteLine(ex.StackTrace); 20 } 21 finally 22 { 23 CloseDatabase(); 24 } 25 } 26 }
TPCollectionExample.cs: TestCollectionPersistence
01private static void TestCollectionPersistence() 02 { 03 StoreCollection(); 04 IObjectContainer container = Database(ConfigureTP()); 05 if (container != null) 06 { 07 try 08 { 09 Team team = (Team)container.QueryByExample(new Team()).Next(); 10 // this method will activate all the members in the collection 11 IList<Pilot> pilots = team.Pilots; 12 foreach (Pilot p in pilots) 13 { 14 p.Name = "Modified: " + p.Name; 15 } 16 team.AddPilot(new Pilot("New pilot")); 17 // explicitly commit to persist changes 18 container.Commit(); 19 } 20 catch (Exception ex) 21 { 22 System.Console.WriteLine(ex.Message); 23 } 24 finally 25 { 26 // If TP changes were not committed explicitly, 27 // they would be persisted with the #close call 28 CloseDatabase(); 29 } 30 } 31 // reopen the database and check the changes 32 container = Database(ConfigureTP()); 33 if (container != null) 34 { 35 try 36 { 37 IObjectSet result = container.QueryByExample(new Team()); 38 Team team = (Team)result[0]; 39 team.ListAllPilots(); 40 } 41 catch (Exception ex) 42 { 43 System.Console.WriteLine(ex.Message); 44 } 45 finally 46 { 47 CloseDatabase(); 48 } 49 } 50 }

TPCollectionExample.vb: StoreCollection
01Private Shared Sub StoreCollection() 02 File.Delete(Db4oFileName) 03 Dim container As IObjectContainer = Database(ConfigureTP()) 04 If container IsNot Nothing Then 05 Try 06 Dim team As New Team() 07 For i As Integer = 0 To 9 08 team.AddPilot(New Pilot("Pilot #" + i.ToString)) 09 Next 10 container.Store(team) 11 container.Commit() 12 Catch ex As Exception 13 System.Console.WriteLine(ex.StackTrace) 14 Finally 15 CloseDatabase() 16 End Try 17 End If 18 End Sub
TPCollectionExample.vb: TestCollectionPersistence
01Private Shared Sub TestCollectionPersistence() 02 StoreCollection() 03 Dim container As IObjectContainer = Database(ConfigureTP()) 04 If container IsNot Nothing Then 05 Try 06 Dim team As Team = DirectCast(container.QueryByExample(New Team()).[Next](), Team) 07 ' this method will activate all the members in the collection 08 Dim pilots As IList(Of Pilot) = team.Pilots 09 For Each p As Pilot In pilots 10 p.Name = "Modified: " + p.Name 11 Next 12 team.AddPilot(New Pilot("New pilot")) 13 ' explicitly commit to persist changes 14 container.Commit() 15 Catch ex As Exception 16 System.Console.WriteLine(ex.Message) 17 Finally 18 ' If TP changes were not committed explicitly, 19 ' they would be persisted with the #close call 20 CloseDatabase() 21 End Try 22 End If 23 ' reopen the database and check the changes 24 container = Database(ConfigureTP()) 25 If container IsNot Nothing Then 26 Try 27 Dim result As IObjectSet = container.QueryByExample(New Team()) 28 Dim team As Team = DirectCast(result(0), Team) 29 team.ListAllPilots() 30 Catch ex As Exception 31 System.Console.WriteLine(ex.Message) 32 Finally 33 CloseDatabase() 34 End Try 35 End If 36 End Sub

So the only thing you should remember when using TP with collections is to use ArrayList4 instead of platform-specific collection.