Object-oriented database programming with db4o - Part 1
In Part 1 and Part 2 of the article entitled The Legend of Data Persistence, I have introduced you to the O-R impedance mismatch, O-R/M tools, ODBMS and its advantages and disadvantages in comparison with RDBMS. Now, once you have decided that you would use an ODBMS for your project, which ODBMS should you use? This article, as a follow-up of The Legend of Data Persistence, aims to introduce you to one of today’s most popular ODBMS implementations, db4objects (db4o).
In the first part of this article, I will introduce you to db4o and show you how to create, update, delete, and query objects with it. In the second part, I will discuss about db4o’s more advanced topics such as transaction and concurrency, custom translator, encryption, networking database, and schema evolution etc. You can file the source code in this article in the Resource section.
I. What is db4o
db4o is an open-source native ODBMS available for both .NET and Java platforms. As a native ODBMS, there is no separate schema kept track by db4o, instead the database schema and application object model are exactly the same, hence, no mapping or transformation is required for persistence and querying. db4o has support for inheritance, deeply nested objects as well as exposes comprehensive query APIs for application developers to queries stored objects.
Regarding usage mode, db4o can be deployed either as an embedded database or as a server-side database. Finally, db4o has support for the schema evolution, indexing, transaction and concurrency, database encryption, and replication service (among db4o databases and certain relational databases). The latest version of db4o is 6.1 and available under two licenses: GPL and a commercial runtime license.
Okay, enough for an introduction, let’s get to the code
II. The Domain Model
While db4o’s strengths are more obvious in applications with highly complex object model, the purpose of this article is more to offer an introduction to db4o, instead of exploring it in every level of dept. As a result, I will use an object model which is very simple but still comprehensive enough to demonstrate features of db4o.
What we have is an object model for a painting application. There are two concrete shape types, Line, Circle, and ShapeList, which implement the IShape interface which has Paint() as its single method. The ShapeList implements the composite design pattern and contains many instances of type IShape. The CPoint represents a 2-D coordination used by Line (start point and end point) and Circle (center point). (Yes, I know there is a System.Drawing.Point, but that Point is a struct, not a class, and since Line and Circle already consist of System.Drawing.Color which is a struct, it is better to have a custom Point class instead to see the differences in how db4o handles classes and structs.)

III. Now, the Code
I will write code using C# 2.0. If you are from the Java space, you should still easily understand the code because the db4o libraries for the two platforms are virtually identical.
The first step we need to do is to download the binary of db4o from its website, and then in VS.NET 2005, add a reference to the Db4objects.Db4o.dll file which is located in the net-2.0 folder of the download.
Below is what the solution explorer looks like after we’ve added the references as well as created the source files needed.
The source code for the model classes are as follows
IShape.cs
public interface IShape
{
void Paint(Graphics graphics);
}
CPoint.cs
public class CPoint
{
private int x;
private int y;
public CPoint(int x, int y)
{
this.x = x;
this.y = y;
}
public int X
{
get {return x;}
set {x = value;}
}
public int Y
{
get {return y;}
set {y = value;}
}
public override bool Equals(object obj)
{
if (obj == null || !(obj is CPoint))
{
return false;
}
CPoint point = obj as CPoint;
return point.x == x && point.y == y;
}
public override int GetHashCode()
{
return x.GetHashCode() + y.GetHashCode();
}
public override string ToString()
{
return string.Format("Point [{0}, {1}]", x, y);
}
}
Circle.cs
public class Circle : IShape
{
private CPoint center;
private Color color;
private float radius;
public Circle(CPoint center, float radius) : this(center, new Color(), radius)
{
}
public Circle(CPoint center, Color color, float radius)
{
this.center = center;
this.color = color;
this.radius = radius;
}
public CPoint Center
{
get {return center;}
set {center = value;}
}
public Color Color
{
get {return color;}
set {color = value;}
}
public float Radius
{
get {return radius;}
set {radius = value;}
}
public override bool Equals(object obj)
{
if (obj == null || !(obj is Circle))
{
return false;
}
Circle circle = obj as Circle;
return (circle.center == null ? center == null : circle.center.Equals(center))
&& (circle.radius == radius)
&& (circle.color.Equals(color));
}
public override int GetHashCode()
{
return center == null ? 0 : center.GetHashCode()
+ color.GetHashCode() + radius.GetHashCode();
}
public override string ToString()
{
return string.Format("Circle [{0}, {1}, {2}]", center, radius, color);
}
public void Paint(Graphics graphics)
{
// No implementation
}
}
Line.cs
public class Line : IShape
private CPoint start;
private CPoint end;
private Color color;
public Line(CPoint start, CPoint end) : this (start, end, new Color())
{
}
public Line(CPoint start, CPoint end, Color color)
{
this.start = start;
this.end = end;
this.color = color;
}
public CPoint Start
{
get {return start;}
set {start = value;}
}
public CPoint End
{
get {return end;}
set {end = value;}
}
public Color Color
{
get {return color;}
set {color = value;}
}
public override bool Equals(object obj)
{
if (obj == null || !(obj is Line))
{
return false;
}
Line line = obj as Line;
return (line.start == null ? start == null : line.start.Equals(start))
&& (line.end == null ? end == null : line.end.Equals(end))
&& (line.color.Equals(color));
}
public override int GetHashCode()
{
return (start == null ? 0 : start.GetHashCode())
+ (end == null ? 0 : end.GetHashCode())
+ color.GetHashCode();
}
public override string ToString()
{
return string.Format("Line [{0}, {1}, {2}]", start, end, color.Name);
}
public void Paint(Graphics graphics)
{
// No implementation
}
}
}
ShapeList.cs
public class ShapeList : IShape private IListshapeList; public ShapeList() { shapeList = new List (); } public void Add(IShape shape) { shapeList.Add(shape); } public void Remove(IShape shape) { shapeList.Remove(shape); } public int Count { get {return shapeList.Count;} } public IShape this[int index] { get {return shapeList[index];} set {shapeList[index] = value;} } public override bool Equals(object obj) { if (obj == null || !(obj is ShapeList)) { return false; } ShapeList otherList = obj as ShapeList; return shapeList.Equals(otherList); } public override int GetHashCode() { return shapeList.GetHashCode(); } public override string ToString() { return shapeList.ToString(); } public void Paint(Graphics graphics) { // No implementation } }
Notes about the coding styles:
- I will use unit test cases to explore and validate the behaviors of db4o, instead of dumping the output to the console. I would love to hear whether this approach makes it easier to understand the code or not.
- I will try to explain the code by using as many comments embedded in the code as possible. That will eliminate much of the text I would have to write (and you would have to read) had I not written the comments but will make the comments more elaborated than I, and possibly some of you, would expect to see in production code.












Good Tool!!! From now, I do not worry about data access layer anymore.
I’ve already intended to use Hibernate in my current java project ;), …but now I think I should change my mind after reading this article.
Thank Buu for your introduction obviously.
To^
I am glad that you like it, Vu. I got to know db4o when evaluating ORM frameworks to be used for a trivial personal .NET project. My first cut was to look at NHibernate and iBATIS.NET and while they are really good tools, I just did not think that it was worth the effort to use any of them in my project. That was when I found out db4o and decided to give it a try. Within about 6 hours I could learn about the API and coded the data layer of my application, something I could not even believe had I not tried it myself.
Of course there is still a long way for db4o to make itself widely adopted in the enterprise space like RDBMS products like Oracle or SQL Server, but I think there is a chance as db4o itself, the tooling, and the community surrounding it become more mature.
[...] have just been recognized as a db4o Most Valued Professional (dVP) for the year 2008 and won a trip to Berlin next year to attend the ICOODB 2008 conference. It [...]
very interesting, but I don’t agree with you
Idetrorce
I want to create a button, when i click that button it will create a
new database (with db4o in Winds Form application (C#)). That code is:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using com.db4o;
using Db4oTools;
using System.IO;
//…………
private void btnThem_Click(object sender, EventArgs e)
{
//File.Delete(Util.YapFileName);
IObjectContainer db = Db4oFactory.OpenFile(Util.YapFileName);
try
{
//
}
finally
{
db.Close();
}
}
and i added: db4o and Db4oTools in References. But i couldn’t create a new database. So, can you help me? Thanks very much!
@Hue:
I suggest you review to see if Util.YapFileName contains the correct link to the db file. If it does, can you describe in detail what the exact problem that you have is? Can you send the stack trace of the exception if any? If there’s no exception, how do you know if you couldn’t create a database?
Thanks very much! I have just created a new database.
I am doing my “plan for graduating” about OODB and I must write a application ( C#.net and db4o). But i don’t have much document about OODB and db4o, i hope you will send for me if you have!
My name’s Hue. I’m a senior student in University of Technical Education HCM City. I am very glad when I know about you!
@Hue:
A great deal of documentation about db4o is located at http://developer.db4o.com/Resources/view.aspx/Documentation (you will need to register for an account).
Or you can refer to this book http://www.amazon.com/Definitive-Guide-db4o-Stefan-Edlich/dp/1590596560, which is by far the only book on db4o. While the book does not contain much depth and is a bit out of date, it should be sufficient for newbies to get up to speed with db4o.
Nice to know you and good luck on your studying!
Thanks very much! And good luck to you everything!