Refactoring API

Db4o provides special API which can help you to move classes between packages (Java)/namespaces(.NET), rename classes or fields:

c#:
Db4oFactory.Configure().ObjectClass("package.class").Rename("newPackage.newClass")
Db4oFactory.Configure().ObjectClass("package.class").ObjectField("oldField").Rename("newField")

VB:
Db4oFactory.Configure().ObjectClass("package.class").Rename("newPackage.newClass")
Db4oFactory.Configure().ObjectClass("package.class").ObjectField("oldField").Rename("newField")

The safe order of actions for rename calls is:

  1. Backup you database and aaplication
  2. Close all open objectContainers if any
  3. Rename classes or fields or copy classes to the new package/namespace in your application. (Do not remove old classes yet).
  4. Issue ObjectClass#rename and objectField#rename calls without having an ObjectContainer open.
  5. Open database file and close it again without actually working with it.
  6. Remove old classes (if applicable).

After that you will only see the new classes/fields in ObjectManager, the old ones will be gone.

Let's look how it works on an example. We will use initial class Pilot:

Pilot.cs
01/* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com */ 02namespace Db4objects.Db4odoc.Refactoring 03{ 04 public class Pilot 05 { 06 private string _name; 07 08 public Pilot(string name) 09 { 10 this._name=name; 11 } 12 13 public string Name 14 { 15 get 16 { 17 return _name; 18 } 19 set 20 { 21 _name = value; 22 } 23 } 24 override public string ToString() 25 { 26 return _name; 27 } 28 } 29}
Pilot.vb
01' Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com 02Namespace Db4objects.Db4odoc.Refactoring 03 Public Class Pilot 04 Private _name As String 05 06 Public Sub New(ByVal name As String) 07 Me._name = name 08 End Sub 09 10 Public Property Name() As String 11 Get 12 Return _name 13 End Get 14 Set(ByVal Value As String) 15 _name = Value 16 End Set 17 End Property 18 Public Overrides Function ToString() As String 19 Return _name 20 End Function 21 End Class 22End Namespace

and change it to the new class PilotNew renaming field and changing package/namespace at the same time:

PilotNew.cs
01/* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com */ 02namespace Db4objects.Db4odoc.Refactoring 03{ 04 public class PilotNew 05 { 06 private string _identity; 07 private int _points; 08 09 public PilotNew(string name, int points) 10 { 11 _identity = name; 12 _points = points; 13 } 14 15 public string Identity 16 { 17 get 18 { 19 return _identity; 20 } 21 } 22 23 override public string ToString() 24 { 25 return string.Format("{0}/{1}",_identity,_points); 26 } 27 } 28}
PilotNew.vb
01' Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com 02Namespace Db4objects.Db4odoc.Refactoring 03 Public Class PilotNew 04 Private _identity As String 05 Private _points As Integer 06 07 Public Sub New(ByVal name As String, ByVal points As Integer) 08 _identity = name 09 _points = points 10 End Sub 11 12 Public ReadOnly Property Identity() As String 13 Get 14 Return _identity 15 End Get 16 End Property 17 18 Public Overrides Function ToString() As String 19 Return String.Format("{0}/{1}", _identity, _points) 20 End Function 21 End Class 22End Namespace

First let's create a database and fill it with some values:

RefactoringExample.cs: SetObjects
01private static void SetObjects() 02 { 03 File.Delete(Db4oFileName); 04 IObjectContainer container = Db4oFactory.OpenFile(Db4oFileName); 05 try 06 { 07 Pilot pilot = new Pilot("Rubens Barrichello"); 08 container.Set(pilot); 09 pilot = new Pilot("Michael Schumacher"); 10 container.Set(pilot); 11 } 12 finally 13 { 14 container.Close(); 15 } 16 }
RefactoringExample.vb: SetObjects
01Private Shared Sub SetObjects() 02 File.Delete(Db4oFileName) 03 Dim container As IObjectContainer = Db4oFactory.OpenFile(Db4oFileName) 04 Try 05 Dim pilot As Pilot = New Pilot("Rubens Barrichello") 06 container.Set(pilot) 07 pilot = New Pilot("Michael Schumacher") 08 container.Set(pilot) 09 Finally 10 container.Close() 11 End Try 12 End Sub
RefactoringExample.cs: CheckDB
01private static void CheckDB() 02 { 03 IObjectContainer container = Db4oFactory.OpenFile(Db4oFileName); 04 try 05 { 06 IObjectSet result = container.Get(typeof(Pilot)); 07 foreach (object obj in result) 08 { 09 Pilot pilot = (Pilot)obj; 10 System.Console.WriteLine("Pilot="+ pilot); 11 } 12 } 13 finally 14 { 15 container.Close(); 16 } 17 }
RefactoringExample.vb: CheckDB
01Private Shared Sub CheckDB() 02 Dim container As IObjectContainer = Db4oFactory.OpenFile(Db4oFileName) 03 Try 04 Dim result As IObjectSet = container.Get(GetType(Pilot)) 05 Dim obj As Object 06 For Each obj In result 07 Dim pilot As Pilot = CType(obj, Pilot) 08 System.Console.WriteLine("Pilot=" + pilot.ToString()) 09 Next 10 Finally 11 container.Close() 12 End Try 13 End Sub

We already have PilotNew class so we can go on with renaming:

RefactoringExample.cs: ChangeClass
1private static void ChangeClass() 2 { 3 IConfiguration configuration = Db4oFactory.NewConfiguration(); 4 configuration.ObjectClass(typeof(Pilot)).Rename("Db4objects.Db4odoc.Refactoring.PilotNew, Db4objects.Db4odoc"); 5 configuration.ObjectClass(typeof(PilotNew)).ObjectField("_name").Rename("_identity"); 6 IObjectContainer container = Db4oFactory.OpenFile(configuration, Db4oFileName); 7 container.Close(); 8 }
RefactoringExample.vb: ChangeClass
1Private Shared Sub ChangeClass() 2 Dim configuration As IConfiguration = Db4oFactory.NewConfiguration() 3 configuration.ObjectClass(GetType(Pilot)).Rename("Db4objects.Db4odoc.Refactoring.PilotNew, Db4objects.Db4odoc") 4 configuration.ObjectClass(GetType(PilotNew)).ObjectField("_name").Rename("_identity") 5 Dim container As IObjectContainer = Db4oFactory.OpenFile(configuration, Db4oFileName) 6 container.Close() 7 End Sub

Now the data for the old Pilot class should be transferred to the new PilotNew class, and "name" field data should be stored in "identity" field.

To make our check more complicated let's add some data for our new class:

RefactoringExample.cs: SetNewObjects
01private static void SetNewObjects() 02 { 03 IObjectContainer container = Db4oFactory.OpenFile(Db4oFileName); 04 try 05 { 06 PilotNew pilot = new PilotNew("Rubens Barrichello",99); 07 container.Set(pilot); 08 pilot = new PilotNew("Michael Schumacher",100); 09 container.Set(pilot); 10 } 11 finally 12 { 13 container.Close(); 14 } 15 }
RefactoringExample.vb: SetNewObjects
01Private Shared Sub SetNewObjects() 02 Dim container As IObjectContainer = Db4oFactory.OpenFile(Db4oFileName) 03 Try 04 Dim pilot As PilotNew = New PilotNew("Rubens Barrichello", 99) 05 container.Set(pilot) 06 pilot = New PilotNew("Michael Schumacher", 100) 07 container.Set(pilot) 08 Finally 09 container.Close() 10 End Try 11 End Sub

We can check what is stored in the database now:

RefactoringExample.cs: RetrievePilotNew
01private static void RetrievePilotNew() 02 { 03 IObjectContainer container = Db4oFactory.OpenFile(Db4oFileName); 04 try 05 { 06 IQuery q = container.Query(); 07 q.Constrain(typeof(PilotNew)); 08 IObjectSet result = q.Execute(); 09 foreach (object obj in result) 10 { 11 PilotNew pilot = (PilotNew)obj; 12 System.Console.WriteLine("Pilot="+ pilot); 13 } 14 } 15 finally 16 { 17 container.Close(); 18 } 19 }
RefactoringExample.vb: RetrievePilotNew
01Private Shared Sub RetrievePilotNew() 02 Dim container As IObjectContainer = Db4oFactory.OpenFile(Db4oFileName) 03 Try 04 Dim q As IQuery = container.Query() 05 q.Constrain(GetType(PilotNew)) 06 Dim result As IObjectSet = q.Execute() 07 Dim obj As Object 08 For Each obj In result 09 Dim pilot As PilotNew = CType(obj, PilotNew) 10 System.Console.WriteLine("Pilot=" + pilot.ToString()) 11 Next 12 Finally 13 container.Close() 14 End Try 15 End Sub

There is one thing to remember. The rename feature is intended to rename a class from one name to the other. Internally this will rename the meta-information. If you will try to rename class to the name that is already stored in the database, the renaming will fail, because the name is reserved. In our example it will happen if setNewObjects method will be called before changeClass.