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:
01/* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com */ 02
using System.Collections.Generic; 03
using System.Collections; 04
05
using Db4objects.Db4o; 06
using Db4objects.Db4o.Activation; 07
using Db4objects.Db4o.TA; 08
using Db4objects.Db4o.Collections; 09
10
namespace 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
}
01' Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com 02
Imports System.Collections.Generic 03
Imports Db4objects.Db4o 04
Imports Db4objects.Db4o.Activation 05
Imports Db4objects.Db4o.TA 06
Imports Db4objects.Db4o.Collections 07
08
09
Namespace 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 70
End 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:
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
}
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
}
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
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.