Tabla de Contenidos

db4objects

Estructura

Con .NET

Una vez instalado en C:\Archivos de programa\Db4objects\db4o-7.8\bin tendremos localizadas las distintas librerías, por ejemplo, la necesaria para utilizar db4o en programas de escritorio es C:\Archivos de programa\Db4objects\db4o-7.8\bin\net-3.5\Db4objects.Db4o.dll.

En Ubuntu puedes conseguir db4o desde el repositorio oficial.

First glance

Primero deberemos incluir la referencia a Db4objects.Db4o y los namespaces necesarios para acceder a las clases que utilizaremos:

using Db4objects.Db4o;

Abrir base de datos

Para abrir una base de datos deberemos llamar al método estático OpenFile de la clase Db4oFactory pasandole la ruta del archivo de DB con el que vayamos a trabajar. Esto devolverá un IObjectContainer que representará a la base de datos.
El método Close del IObjectContainer cerrará la DB.

IObjectContainer db = Db4oFactory.OpenFile(@"c:\prueba.db");
try {
  // Operaciones con la base de datos
}
finally {
  db.Close();
}

Versión 6.0 en Mono

La versión 6.0 es una versión accesible con las versiones actuales de Mono (21 de febrero de 2010), sobre ella puede utilizarse LINQ y es perfectamente usable. Aún así no utilices un ObjectManager de una versión superior sobre una DB de esta versión porque la corromperá.

Queries

Recoger todos los elementos de un tipo

Para ello lo haremos con el método Get del IObjectContainer, pudiendo hacerlo de dos formas:

  1. Pasándole el tipo del que queremos todos los elementos mediante el typeof.
  2. Pasándole un objeto vacío del tipo que buscamos.
// Forma 1:
IObjectSet result = db.Get(typeof(Car));
foreach (var b in result)
    Console.WriteLine(((Car)b).marca);
// Forma 2:
IObjectSet result = db.Get(new Car () { marca = null });

Filtrar elementos

Para lanzar la consulta simplemente llamaríamos al Get sólo asignando la propiedad por la que queremos buscar:

IObjectSet result = db.Get(new Pilot () { Name = "Pedro" });

Utilizando el método Query (Native Query)

Podemos utilizar el método Query que requiere de un delegado que reciba por parámetro el tipo de elemento consultado y que devuelva un bool, de esa forma internamente se va llamando a este por cada elemento y se comprueba lo deseado.

public IList<Pilot> GetThePilot (Pilot templatePilot)
{
    IList<Pilot> pilots = db.Query<Pilot> ( 
        delegate(Pilot match)
        {
            return ((match.name == templatePilot.name) && (match.id == templatePilot.id))
        } );
    return pilots;
}

Queries con LINQ

Aunque las versiones anteriores de Mono tienen un uso bastante precario de LINQ este sí que puede ser aprovechado para las consultas a una base de datos db4o.
La siguiente query busca el nombre de los pilotos con un mini ordenando el resultado por el número de coches que estos tienen:

var result = from p in db.Query<Pilot>()
             from c in p.lCars
             where (c.marca == "MINI")
             orderby p.lCars.Count
             select p;
foreach (var r in result)
    System.Console.WriteLine(r.name);

Notas

var template = new Car () { marca = null };
var result = db.Get(template).Cast<Car>();
var first = result.FirstOrDefault();
var list = result.ToList();

Acciones básicas

class Pilot
{
    public int id {get; set; }
    public string name {get; set;}
    public List<Car> lCars = new List<Car>();
}
class Car
{
    public string marca;
}

Insertar

Para insertar un elemento llamaremos al método Set:

db.Set(new Pilot () { id = 1, name = "Juan" });

Si un objeto insertado tiene otros objetos internamente (como por ejemplo la clase Pilot que tiene una lista de la Car) aparecerá en la base de datos otra “tabla” con los objetos, por ejemplo objetos Car de los Pilot que se van insertando.
Si en el código se ha asignado un mismo Car a varios Pilot no se duplicará en la tabla de la clase Car.
Al eliminar objetos Pilot no se eliminarán los Car en la tabla.

Actualizar

Para actualizar un elemento símplemente tenemos que recoger lo que queramos actualizar, cambiarlo y volver a colocarlo en la DB llamando al método Set.
La siguiente consulta recoge todos los pilotos con un coche “mini” y actualiza sus nombres agregandoles “minimalistas”.

IObjectContainer db = Db4oFactory.OpenFile("prueba.db");
var result = from p in db.Query<Pilot>()
             from c in p.lCars
             where (c.marca == "MINI")
             select p;
foreach (var r in result)
{
    r.name = r.name + " - Minimalistas";
    db.Set(r);
}
db.Close();

Eliminar

Eliminar funciona igual que actualizar, únicamente cambia la llamada al método de la DB, esta vez el método es Delete.
El siguiente código elimina todos los pilotos que tengan un mini:

var result = from p in db.Query<Pilot>()
             from c in p.lCars
             where c.marca == "MINI"
             select p;
foreach (var r in result)
    db.Delete(r);

Acciones avanzadas

Generación de IDs

db4o por defecto genera un identificador long para cada objeto insertado en la DB.
Para coger la id de un objeto haremos: db.Ext().GetID(object);
Para coger un objeto a partir de su id haremos: db.Ext().GetByID(id);

Opcionalmente también se pueden generar los UUID (Unique Universal IDs), que son identificadores universales para que elementos que se compartan entre diferentes DB.

Indexar un campo

Para crear un índice deberemos de poner la siguiente línia antes de abrir la base de datos:

Db4oFactory.Configure().ObjectClass(typeof(NombreClase)).ObjectField("NombreCampo").Indexed(true);

El campo que queramos indexar no puede ser un campo autoimplementado, es decir, que sea así:

int id { get; set; }

Sería algo así:

class Program
{
    public int id;
    public int name;
    static void Main(string[] args)
    {
        Db4oFactory.Configure().ObjectClass(typeof(Program)).ObjectField("id").Indexed(true);
        var db = Db4oFactory.OpenFile("c:\\prueba.db");
...

Creación de servidor

Embedded

Para usar accesos concurrentes desde un mismo ejecutable:

IObjectServer server = Db4oFactory.OpenServer(dbPath, 0);
IObjectContainer client1 = server.OpenClient();
IObjectContainer client2 = server.OpenClient();
// ...
client1.Close();
client2.Close();
server.Close();

En red

Para que funcione en red, el servidor:

public void Start()
{
    lock (this)
    {
        IObjectServer server = Db4oFactory.OpenServer("c:\\db.db4o", 1258);
        server.GrantAccess(USER, PASSWORD);
        Monitor.Wait(this);
    }
}

Y el cliente:

IObjectContainer db = Db4oFactory.OpenClient(SERVER_HOST, 1258, USER, PASSWORD);