Let's look at a primitive example, demonstrating manual implementation of Activatable/IActivatable interface for TP. We will use a class similar to the one used in Transparent Activation chapters.
001/* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com */ 002
using Db4objects.Db4o; 003
using Db4objects.Db4o.Activation; 004
using Db4objects.Db4o.TA; 005
006
namespace Db4ojects.Db4odoc.TPExample 007
{ 008
public class SensorPanel /*must implement Activatable for TA and TP */: IActivatable 009
{ 010
private object _sensor; 011
012
private SensorPanel _next; 013
014
/*activator registered for this class*/ 015
[System.NonSerialized] 016
IActivator _activator; 017
018
public SensorPanel() 019
{ 020
// default constructor for instantiation 021
} 022
// end SensorPanel 023
024
public SensorPanel(int value) 025
{ 026
_sensor = value; 027
} 028
// end SensorPanel 029
030
/*Bind the class to the specified object container, create the activator*/ 031
public void Bind(IActivator activator) 032
{ 033
if (_activator == activator) 034
{ 035
return; 036
} 037
if (activator != null && null != _activator) 038
{ 039
throw new System.InvalidOperationException(); 040
} 041
_activator = activator; 042
} 043
// end Bind 044
045
/*Call the registered activator to activate the next level, 046
* the activator remembers the objects that were already 047
* activated and won't activate them twice. 048
*/ 049
public void Activate(ActivationPurpose purpose) 050
{ 051
if (_activator == null) 052
return; 053
_activator.Activate(purpose); 054
} 055
// end Activate 056
057
public SensorPanel Next 058
{ 059
get 060
{ 061
/*activate direct members*/ 062
Activate(ActivationPurpose.Read); 063
return _next; 064
} 065
} 066
// end Next 067
068
public object Sensor 069
{ 070
get 071
{ 072
/*activate direct members*/ 073
Activate(ActivationPurpose.Read); 074
return _sensor; 075
} 076
set 077
{ 078
/*activate for persistense*/ 079
Activate(ActivationPurpose.Write); 080
_sensor = value; 081
} 082
} 083
// end Sensor 084
085
public SensorPanel CreateList(int length) 086
{ 087
return CreateList(length, 1); 088
} 089
// end CreateList 090
091
public SensorPanel CreateList(int length, int first) 092
{ 093
int val = first; 094
SensorPanel root = NewElement(first); 095
SensorPanel list = root; 096
while (--length > 0) 097
{ 098
list._next = NewElement(++val); 099
list = list.Next; 100
} 101
return root; 102
} 103
// end CreateList 104
105
protected SensorPanel NewElement(int value) 106
{ 107
return new SensorPanel(value); 108
} 109
// end NewElement 110
111
public override string ToString() 112
{ 113
return "Sensor #" + Sensor; 114
} 115
// end ToString 116
} 117
118
}
001' Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com 002
Imports Db4objects.Db4o 003
Imports Db4objects.Db4o.Activation 004
Imports Db4objects.Db4o.TA 005
006
Namespace Db4ojects.Db4odoc.TPExample 007
008
Public Class SensorPanel ' must implement Activatable for TA and TP 009
Implements IActivatable 010
011
Private _sensor As Object 012
Private _next As SensorPanel 013
014
' activator registered for this class 015
<Transient()> _ 016
Private _activator As IActivator 017
018
Public Sub New() 019
End Sub 020
' end New 021
022
Public Sub New(ByVal value As Integer) 023
_sensor = value 024
End Sub 025
' end New 026
027
' Bind the class to the specified object container, create the activator 028
Public Sub Bind(ByVal activator As IActivator) Implements IActivatable.Bind 029
If _activator Is activator Then 030
Return 031
End If 032
If Not (activator Is Nothing Or _activator Is Nothing) Then 033
Throw New System.InvalidOperationException() 034
End If 035
_activator = activator 036
End Sub 037
' end Bind 038
039
'Call the registered activator to activate the next level, 040
' the activator remembers the objects that were already 041
' activated and won't activate them twice. 042
Public Sub Activate(ByVal purpose As ActivationPurpose) Implements IActivatable.Activate 043
If _activator Is Nothing Then 044
Return 045
End If 046
_activator.Activate(ActivationPurpose.Read) 047
End Sub 048
' end Activate 049
050
Public ReadOnly Property NextSensor() As SensorPanel 051
Get 052
' activate direct members 053
Activate(ActivationPurpose.Read) 054
Return _next 055
End Get 056
End Property 057
' end NextSensor 058
059
Public Property Sensor() As Object 060
Get 061
' activate direct members 062
Activate(ActivationPurpose.Read) 063
Return _sensor 064
End Get 065
Set(ByVal value As Object) 066
' activate for persistence 067
Activate(ActivationPurpose.Write) 068
_sensor = value 069
End Set 070
End Property 071
' end Sensor 072
073
Public Function CreateList(ByVal length As Integer) As SensorPanel 074
Return CreateList(length, 1) 075
End Function 076
' end CreateList 077
078
Public Function CreateList(ByVal length As Integer, ByVal first As Integer) As SensorPanel 079
Dim val As Integer = first 080
Dim root As SensorPanel = NewElement(first) 081
Dim list As SensorPanel = root 082
While System.Threading.Interlocked.Decrement(length) > 0 083
list._next = NewElement(System.Threading.Interlocked.Increment(val)) 084
list = list.NextSensor 085
End While 086
Return root 087
End Function 088
' end CreateList 089
090
Protected Function NewElement(ByVal value As Integer) As SensorPanel 091
Return New SensorPanel(value) 092
End Function 093
' end NewElement 094
095
Public Overloads Overrides Function ToString() As String 096
Return "Sensor #" + Sensor.ToString() 097
End Function 098
' end ToString 099
End Class 100
End Namespace
Note, that the only place where we can modify SensorPanel members
is setSensor
method/Sensor
property, and that is
where activate
method is added.
Now we will only need to add Transparent Activation support:
1private static IConfiguration ConfigureTA() 2
{ 3
IConfiguration configuration = Db4oFactory.NewConfiguration(); 4
// add TA support 5
configuration.Add(new TransparentActivationSupport()); 6
return configuration; 7
}
1Private Shared Function ConfigureTA() As IConfiguration 2
Dim configuration As IConfiguration = Db4oFactory.NewConfiguration 3
' add TA support 4
configuration.Add(New TransparentActivationSupport) 5
Return configuration 6
End Function
Initial storing of the objects is done as usual with a
single store
call:
01private static void StoreSensorPanel() 02
{ 03
File.Delete(Db4oFileName); 04
IObjectContainer container = Database(Db4oFactory.NewConfiguration()); 05
if (container != null) 06
{ 07
try 08
{ 09
// create a linked list with length 10 10
SensorPanel list = new SensorPanel().CreateList(10); 11
container.Store(list); 12
} 13
finally 14
{ 15
CloseDatabase(); 16
} 17
} 18
}
01Private Shared Sub StoreSensorPanel() 02
File.Delete(Db4oFileName) 03
Dim container As IObjectContainer = Database(Db4oFactory.NewConfiguration) 04
If Not (container Is Nothing) Then 05
Try 06
' create a linked list with length 10 07
Dim list As SensorPanel = (New SensorPanel).CreateList(10) 08
container.Set(list) 09
Finally 10
CloseDatabase() 11
End Try 12
End If 13
End Sub
Now we can test how Transparent Persistence helped us to keep the code simple. Let's select all elements from the linked SensorPanel list, modify them and store. As you remember default update depth is one, so without TP, we would have to store each member of the linked list (SensorPanel) separately. With TP enabled there is absolutely nothing to do: commit call will find all activatable objects and store those that were modified.
01private static void TestTransparentPersistence() 02
{ 03
StoreSensorPanel(); 04
IConfiguration configuration = ConfigureTA(); 05
06
IObjectContainer container = Database(configuration); 07
if (container != null) 08
{ 09
try 10
{ 11
IObjectSet result = container.QueryByExample(new SensorPanel(1)); 12
ListResult(result); 13
SensorPanel sensor = null; 14
if (result.Size() > 0) 15
{ 16
System.Console.WriteLine("Before modification: "); 17
sensor = (SensorPanel)result[0]; 18
// the object is a linked list, so each call to next() 19
// will need to activate a new object 20
SensorPanel next = sensor.Next; 21
while (next != null) 22
{ 23
System.Console.WriteLine(next); 24
// modify the next sensor 25
next.Sensor = (object)(10 + (int)next.Sensor); 26
next = next.Next; 27
} 28
// Explicit commit stores and commits the changes at any time 29
container.Commit(); 30
} 31
} 32
finally 33
{ 34
// If there are unsaved changes to activatable objects, they 35
// will be implicitly saved and committed when the database 36
// is closed 37
CloseDatabase(); 38
} 39
} 40
// reopen the database and check the modifications 41
container = Database(configuration); 42
if (container != null) 43
{ 44
try 45
{ 46
IObjectSet result = container.QueryByExample(new SensorPanel(1)); 47
ListResult(result); 48
SensorPanel sensor = null; 49
if (result.Size() > 0) 50
{ 51
System.Console.WriteLine("After modification: "); 52
sensor = (SensorPanel)result[0]; 53
SensorPanel next = sensor.Next; 54
while (next != null) 55
{ 56
System.Console.WriteLine(next); 57
next = next.Next; 58
} 59
} 60
} 61
finally 62
{ 63
CloseDatabase(); 64
} 65
} 66
}
01Private Shared Sub TestTransparentPersistence() 02
StoreSensorPanel() 03
Dim configuration As IConfiguration = ConfigureTA() 04
Dim container As IObjectContainer = Database(configuration) 05
If Not (container Is Nothing) Then 06
Try 07
Dim result As IObjectSet = container.QueryByExample(New SensorPanel(1)) 08
Dim sensor As SensorPanel = Nothing 09
ListResult(result) 10
If result.Size > 0 Then 11
System.Console.WriteLine("Before modification: ") 12
sensor = CType(result(0), SensorPanel) 13
' the object is a linked list, so each call to next() 14
' will need to activate a new object 15
Dim nextSensor As SensorPanel = sensor.NextSensor 16
While Not (nextSensor Is Nothing) 17
System.Console.WriteLine(nextSensor) 18
' modify the next sensor 19
nextSensor.Sensor = CType((10 + CType(nextSensor.Sensor, Int32)), Object) 20
nextSensor = nextSensor.NextSensor 21
End While 22
End If 23
Finally 24
CloseDatabase() 25
End Try 26
End If 27
' reopen the database and check the modifications 28
container = Database(configuration) 29
If Not (container Is Nothing) Then 30
Try 31
Dim result As IObjectSet = container.QueryByExample(New SensorPanel(1)) 32
Dim sensor As SensorPanel = Nothing 33
ListResult(result) 34
If result.Size > 0 Then 35
System.Console.WriteLine("After modification: ") 36
sensor = CType(result(0), SensorPanel) 37
Dim nextSensor As SensorPanel = sensor.NextSensor 38
While Not (nextSensor Is Nothing) 39
System.Console.WriteLine(nextSensor) 40
nextSensor = nextSensor.NextSensor 41
End While 42
End If 43
Finally 44
CloseDatabase() 45
End Try 46
End If 47
End Sub
That's all. The benefits that we've got: