Static fields API

By default db4o does not persist static fields. Normally this is not necessary as static values are set for a class, not for an object. However you can set up db4o to store static fields if you need to implement constant or enumeration:

c#:

Db4oFactory.Configure().ObjectClass(typeof(Foo)).PersistStaticFieldValues()

VB:

Db4oFactory.Configure().ObjectClass(GetType(Foo)).PersistStaticFieldValues()

Do not use this option unnecessarily, as it will slow down the process of opening database files and the stored objects will occupy space in the database file.

This option does not have any eaffect on primitive types (int, boolean, etc). Use their object alternatives instead (Integer, Boolean, etc).

When this setting is on for a specific class, all non-primitive-typed static field values of this class are stored the first time an object of the class is stored, and restored, every time a database file is opened afterwards, after class meta information is loaded for this class (when the class objects are retrieved with a query, for example).

A good example of non-primitive constant type is type-safe enumeration implementation:

PilotCategories.cs
01namespace Db4objects.Db4odoc.StaticFields 02{ 03 public class PilotCategories 04 { 05 private string _qualification = null; 06 public static PilotCategories Winner = new PilotCategories("WINNER"); 07 public static PilotCategories Talented = new PilotCategories("TALENTED"); 08 public static PilotCategories Average = new PilotCategories("AVERAGE"); 09 public static PilotCategories Disqualified = new PilotCategories("DISQUALIFIED"); 10 11 private PilotCategories(string qualification) 12 { 13 this._qualification = qualification; 14 } 15 16 public PilotCategories() 17 { 18 19 } 20 21 public void TestChange(string qualification) 22 { 23 this._qualification = qualification; 24 } 25 26 override public string ToString() 27 { 28 return _qualification; 29 } 30 } 31}
PilotCategories.vb
01' Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com 02 03Namespace Db4objects.Db4odoc.StaticFields 04 Public Class PilotCategories 05 Private _qualification As String = Nothing 06 Public Shared WINNER As PilotCategories = New PilotCategories("WINNER") 07 Public Shared TALENTED As PilotCategories = New PilotCategories("TALENTED") 08 Public Shared AVERAGE As PilotCategories = New PilotCategories("AVERAGE") 09 Public Shared DISQUALIFIED As PilotCategories = New PilotCategories("DISQUALIFIED") 10 11 Private Sub New(ByVal qualification As String) 12 Me._qualification = qualification 13 End Sub 14 15 Public Sub New() 16 17 End Sub 18 19 Public Sub TestChange(ByVal qualification As String) 20 Me._qualification = qualification 21 End Sub 22 23 Public Overrides Function ToString() As String 24 Return _qualification 25 End Function 26 End Class 27End Namespace

Let's use it with

Pilot.cs
01/* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com */ 02namespace Db4objects.Db4odoc.StaticFields 03{ 04 public class Pilot 05 { 06 private string _name; 07 private PilotCategories _category; 08 09 public Pilot(string name,PilotCategories category) 10 { 11 _name=name; 12 _category=category; 13 } 14 15 public PilotCategories Category 16 { 17 get 18 { 19 return _category; 20 } 21 } 22 23 public string Name 24 { 25 get 26 { 27 return _name; 28 } 29 } 30 31 override public string ToString() 32 { 33 return string.Format("{0}/{1}", _name, _category); 34 } 35 } 36}
Pilot.vb
01' Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com 02 03Namespace Db4objects.Db4odoc.StaticFields 04 Public Class Pilot 05 Private _name As String 06 Private _category As PilotCategories 07 08 Public Sub New(ByVal name As String, ByVal Category As PilotCategories) 09 Me._name = name 10 Me._category = Category 11 End Sub 12 13 Public ReadOnly Property Category() As PilotCategories 14 Get 15 Return _category 16 End Get 17 End Property 18 19 Public ReadOnly Property Name() As String 20 Get 21 Return _name 22 End Get 23 End Property 24 25 Public Overrides Function ToString() As String 26 Return String.Format("{0}/{1}", _name, _category) 27 End Function 28 End Class 29End Namespace
StaticFieldExample.cs: SetPilots
01private static void SetPilots() 02 { 03 File.Delete(Db4oFileName); 04 IObjectContainer db = Database(); 05 if (db != null) 06 { 07 try 08 { 09 db.Set(new Pilot("Michael Schumacher", PilotCategories.Winner)); 10 db.Set(new Pilot("Rubens Barrichello", PilotCategories.Talented)); 11 } 12 finally 13 { 14 CloseDatabase(); 15 } 16 } 17 }
StaticFieldExample.vb: SetPilots
01Private Shared Sub SetPilots() 02 File.Delete(Db4oFileName) 03 Dim db As IObjectContainer = Database() 04 If db IsNot Nothing Then 05 Try 06 db.[Set](New Pilot("Michael Schumacher", PilotCategories.Winner)) 07 db.[Set](New Pilot("Rubens Barrichello", PilotCategories.Talented)) 08 Finally 09 CloseDatabase() 10 End Try 11 End If 12 End Sub

We can try to save pilots with the default db4o settings:

StaticFieldExample.cs: CheckPilots
01private static void CheckPilots() 02 { 03 IObjectContainer db = Database(); 04 if (db != null) 05 { 06 try 07 { 08 IObjectSet result = db.Get(typeof(Pilot)); 09 foreach (object obj in result) 10 { 11 Pilot pilot = (Pilot)obj; 12 if (pilot.Category == PilotCategories.Winner) 13 { 14 Console.WriteLine("Winner pilot: " + pilot); 15 } 16 else if (pilot.Category == PilotCategories.Talented) 17 { 18 Console.WriteLine("Talented pilot: " + pilot); 19 } 20 else 21 { 22 Console.WriteLine("Uncategorized pilot: " + pilot); 23 } 24 } 25 } 26 finally 27 { 28 CloseDatabase(); 29 } 30 } 31 }
StaticFieldExample.vb: CheckPilots
01Private Shared Sub CheckPilots() 02 Dim db As IObjectContainer = Database() 03 If db IsNot Nothing Then 04 Try 05 Dim result As IObjectSet = db.[Get](GetType(Pilot)) 06 Dim obj As Object 07 For Each obj In result 08 Dim pilot As Pilot = DirectCast(obj, Pilot) 09 If pilot.Category Is PilotCategories.WINNER Then 10 Console.WriteLine("Winner pilot: " + pilot.ToString()) 11 ElseIf pilot.Category Is PilotCategories.TALENTED Then 12 Console.WriteLine("Talented pilot: " + pilot.ToString()) 13 Else 14 Console.WriteLine("Uncategorized pilot: " + pilot.ToString()) 15 End If 16 Next 17 Finally 18 CloseDatabase() 19 End Try 20 End If 21 End Sub

That does not work however. We will have to explicitly point out, which class's static fields we want to save:

StaticFieldExample.cs: Configure
1private static void Configure() { 2 System.Console.WriteLine("Saving static fields can be turned on for individual classes."); 3 _configuration = Db4oFactory.NewConfiguration(); 4 _configuration.ObjectClass(typeof(PilotCategories)).PersistStaticFieldValues(); 5 }
StaticFieldExample.vb: Configure
1Private Shared Sub Configure() 2 System.Console.WriteLine("Saving static fields can be turned on for individual classes.") 3 _configuration = Db4oFactory.NewConfiguration() 4 _configuration.ObjectClass(GetType(PilotCategories)).PersistStaticFieldValues() 5 End Sub

Try to save and check pilots again - you should see that with this configuration enumeration values are actually correctly bound to their runtime values.

As it was mentioned before, it is important to keep static values in one place and do not allow different objects to modify them. If we try to change static value from the referencing object:

StaticFieldExample.cs: UpdatePilots
01private static void UpdatePilots() 02 { 03 Console.WriteLine("Updating PilotCategory in pilot reference:"); 04 IObjectContainer db = Database(); 05 if (db != null) 06 { 07 try 08 { 09 IObjectSet result = db.Get(typeof(Pilot)); 10 foreach (object obj in result) 11 { 12 Pilot pilot = (Pilot)obj; 13 if (pilot.Category == PilotCategories.Winner) 14 { 15 Console.WriteLine("Winner pilot: " + pilot); 16 PilotCategories pc = pilot.Category; 17 pc.TestChange("WINNER2006"); 18 db.Set(pilot); 19 } 20 } 21 PrintCategories(db); 22 } 23 finally 24 { 25 CloseDatabase(); 26 } 27 } 28 }
StaticFieldExample.vb: UpdatePilots
01Private Shared Sub UpdatePilots() 02 Console.WriteLine("Updating PilotCategory in pilot reference:") 03 Dim db As IObjectContainer = Database() 04 If db IsNot Nothing Then 05 Try 06 Dim result As IObjectSet = db.[Get](GetType(Pilot)) 07 Dim obj As Object 08 For Each obj In result 09 Dim pilot As Pilot = DirectCast(obj, Pilot) 10 If pilot.Category Is PilotCategories.WINNER Then 11 Console.WriteLine("Winner pilot: " + pilot.ToString()) 12 Dim pc As PilotCategories = pilot.Category 13 pc.TestChange("WINNER2006") 14 db.[Set](pilot) 15 End If 16 Next 17 PrintCategories(db) 18 Finally 19 CloseDatabase() 20 End Try 21 End If 22 End Sub

the value just does not change. You can check it with the checkPilots method above.

In order to update static field we will have to do that explicitly:
StaticFieldExample.cs: UpdatePilotCategories
01private static void UpdatePilotCategories() 02 { 03 Console.WriteLine("Updating PilotCategories explicitly:"); 04 IObjectContainer db = Database(); 05 if (db != null) 06 { 07 try 08 { 09 IObjectSet result = db.Get(typeof(PilotCategories)); 10 foreach (object obj in result) 11 { 12 PilotCategories pc = (PilotCategories)obj; 13 if (pc == PilotCategories.Winner) 14 { 15 pc.TestChange("WINNER2006"); 16 db.Set(pc); 17 } 18 } 19 PrintCategories(db); 20 } 21 finally 22 { 23 CloseDatabase(); 24 } 25 } 26 }
StaticFieldExample.vb: UpdatePilotCategories
01Private Shared Sub UpdatePilotCategories() 02 Console.WriteLine("Updating PilotCategories explicitly:") 03 Dim db As IObjectContainer = Database() 04 If db IsNot Nothing Then 05 Try 06 Dim result As IObjectSet = db.[Get](GetType(PilotCategories)) 07 Dim obj As Object 08 For Each obj In result 09 Dim pc As PilotCategories = DirectCast(obj, PilotCategories) 10 If pc Is PilotCategories.WINNER Then 11 pc.TestChange("WINNER2006") 12 db.[Set](pc) 13 End If 14 Next 15 PrintCategories(db) 16 Finally 17 CloseDatabase() 18 End Try 19 End If 20 End Sub
Please, check the result with the checkPilots method. You will see that the reference has changed correctly.

What about deletion? Similar to update we cannot delete static fields from the referenced object, but we can delete them directly from the database:

StaticFieldExample.cs: AddDeleteConfiguration
1private static void AddDeleteConfiguration() { 2 if (_configuration != null) { 3 _configuration.ObjectClass(typeof(Pilot)).CascadeOnDelete(true); 4 } 5 }
StaticFieldExample.cs: DeleteTest
01private static void DeleteTest() 02 { 03 IObjectContainer db = Database(); 04 if (db != null) 05 { 06 try 07 { 08 Console.WriteLine("Deleting Pilots :"); 09 IObjectSet result = db.Get(typeof(Pilot)); 10 foreach (object obj in result) 11 { 12 Pilot pilot = (Pilot)obj; 13 db.Delete(pilot); 14 } 15 PrintCategories(db); 16 Console.WriteLine("Deleting PilotCategories :"); 17 result = db.Get(typeof(PilotCategories)); 18 foreach (object obj in result) 19 { 20 db.Delete(obj); 21 } 22 PrintCategories(db); 23 } 24 finally 25 { 26 CloseDatabase(); 27 } 28 } 29 }

StaticFieldExample.vb: AddDeleteConfiguration
1Private Shared Sub AddDeleteConfiguration() 2 If _configuration IsNot Nothing Then 3 _configuration.ObjectClass(GetType(Pilot)).CascadeOnDelete(True) 4 End If 5 End Sub
StaticFieldExample.vb: DeleteTest
01Private Shared Sub DeleteTest() 02 Dim db As IObjectContainer = Database() 03 If db IsNot Nothing Then 04 Try 05 Console.WriteLine("Deleting Pilots :") 06 Dim result As IObjectSet = db.[Get](GetType(Pilot)) 07 Dim obj As Object 08 For Each obj In result 09 Dim pilot As Pilot = DirectCast(obj, Pilot) 10 db.Delete(pilot) 11 Next 12 PrintCategories(db) 13 Console.WriteLine("Deleting PilotCategories :") 14 result = db.[Get](GetType(PilotCategories)) 15 For Each obj In result 16 db.Delete(obj) 17 Next 18 PrintCategories(db) 19 Finally 20 CloseDatabase() 21 End Try 22 End If 23 End Sub