db4o A light weight Object Oriented Database
Now a days I am spending my free time in rewriting one of my freeware for Flickr users called iTraveller. One of the design goals was the application should be scalable. My major concern was, I cannot freeze my db design before my first release because I am planning to have multiple version with added functionalities, so the db structure may change in the future. If I use conventional db’s then I have to write functionality to add or remove columns. iTraveller is not very data centric application, so managing db change scripts and writing a functionality to apply these changes when user upgrade to new version will be a big pain for me.
First I thought of using MongoDB, because I used Mongo db in a Silverlight application. But then finally dropped that idea. I want some thing more lighter than Mongo and NoSql sort of database. I evaluated several db’s but nothing suites what I am looking for. Finally my search ends at db4o. The usage of db4o is very straight forward and very easy to learn, db4o installer comes with a very good documentation to start off with the development.
db4o is a light weight Object Oriented database. Using db4o I can persist my entities very easily without any configuration. I can add or remove new properties to my entities without affecting the existing persisted entities.
I created a generic repository sort of class around db4o, the same way I did one for Entity Framework. This generic repository reduced lot of my work and act as the entry point to persist my entities to db4o data file. Below is the Generic repository I created for db4o.
using Db4objects.Db4o;
public class GenericRepository:IRepository,IDisposable { private static IRepository _singleRepoInstance; public const string DBNAME = "Data.dat"; public static IRepository GetRepositoryInstance() { if (_singleRepoInstance == null) _singleRepoInstance = new GenericRepository(); return _singleRepoInstance; } IObjectContainer _context = null; private IObjectContainer Context { get { if(_context==null) _context = Db4oFactory.OpenFile(DBNAME); return _context; } } private IList<TEntity> Query<TEntity>() where TEntity : class { return this.Context.Query<TEntity>(); } public IList<TEntity> GetAll<TEntity>() where TEntity : class { return this.Query<TEntity>().ToList(); } public IList<TEntity> GetAll<TEntity>(TEntity entity) where TEntity : class { return this.Context.QueryByExample(entity).Cast<TEntity>().ToList(); } public IList<TEntity> Find<TEntity>(Func<TEntity, bool> criteria) where TEntity : class { return this.Query<TEntity>().Where<TEntity>(criteria).ToList<TEntity>(); } public TEntity Single<TEntity>(Func<TEntity, bool> criteria) where TEntity : class { return this.Query<TEntity>().Single<TEntity>(criteria); } public TEntity First<TEntity>(Func<TEntity, bool> criteria) where TEntity : class { return this.Query<TEntity>().FirstOrDefault<TEntity>(criteria); } public TEntity First<TEntity>(TEntity criteria) where TEntity : class { return this.Context.QueryByExample(criteria).Cast<TEntity>().First<TEntity>(); } public void Add<TEntity>(TEntity entity) where TEntity : class { this.Context.Store(entity); } public void Add<TEntity>(List<TEntity> entities) where TEntity : class { foreach (TEntity entity in entities) { this.Add<TEntity>(entity); } } public void Delete<TEntity>(TEntity entity) where TEntity : class { this.Context.Delete(entity); } public void Update<TEntity>(TEntity entity) where TEntity : class { this.Context.Store(entity); } public void Dispose() { this._context.Close(); this._context.Dispose(); this._context = null; } }
The above repository is created in singletone mode. I did that way because I noticed that opening the database file is taking some delay and wanted to avoid that delay. So I wont close the data file until iTraveller get closed.
Let’s see how we can call the above repository to save an entity
GenericRepository repository = GenericRepository.GetRepositoryInstance(); repository.Add<Photo>(photos);
Below is the way we can retrieve some entities from the data file
IRepository repository = GenericRepository.GetRepositoryInstance(); List<LocalCategory> categories = repository.GetAll<LocalCategory>().ToList<LocalCategory>();
You can also retrieve data based on any condition as well. The below code will return a list of Photo object whose categoryId is 10.
IRepository repository = GenericRepository.GetRepositoryInstance(); return repository.Find<Photo>(p => p.Category.ID == 10).ToList<Photo>();
As you can see the db4o is very easy to use light weight database without the hurdles of mapping to tables and all sort of stuffs.
[…] used db4o for persisting my data, I covered how I used db4o in one of my previous post. Let’s start the code walk through from Application layer. In my app layer I have a function to […]
Populate Listbox Incrementally using Await and Reactive Extension (Rx) | Sony Arouje Blog
February 15, 2011 at 6:24 pm
Where can I download the source for iTraveller
I cannot find it here:
http://itraveller.googlecode.com/svn/trunk/
Basarat Ali Syed
March 15, 2011 at 2:00 pm
iTraveller’s source is not released, you can download only the setup.
sonyarouje
March 15, 2011 at 2:04 pm
Hey,
Great blog – I’m enjoying reading your posts. Question about db4o (I’ve looked at the documentation but..): If I store some objects of type ‘Employee’ which all have a property of type ‘Role’ (which often point to the same Role), is it possible to then query and return a list of ‘Roles’? Or are object properties only stored on the object and not separately indexed? Thanks.
andrew
May 5, 2011 at 8:27 pm
Yes you can get a list of Roles, It stored separately. I was also confused the same way like you. Then I did couple of tracers to make myself confident before using it in iTraveller.
Thanks for reading my post.
Sony Arouje
May 6, 2011 at 8:07 am
this could be the most abstract implementation of repository pattern and Db4o. thanks for sharing !
Amr Ellafy
October 9, 2011 at 7:17 pm
Thanks Amr.
Sony Arouje
October 10, 2011 at 11:04 am
[…] start with repository, I used the same kind of repository I created for iTraveller with some changes in creating the db4o context/container. The change is as shown […]
Transparent Persistence with db4o | Sony Arouje Blog
August 8, 2012 at 12:44 pm