Building SODA Queries

Let's see how simple QBE queries are expressed with SODA. A new Query object is created through the #query() method of the ObjectContainer and we can add Constraint instances to it. To find all Pilot instances, we constrain the query with the Pilot class object.

QueryExample.cs: RetrieveAllPilots
01public static void RetrieveAllPilots() 02 { 03 IObjectContainer db = Db4oFactory.OpenFile(YapFileName); 04 try 05 { 06 IQuery query = db.Query(); 07 query.Constrain(typeof(Pilot)); 08 IObjectSet result = query.Execute(); 09 ListResult(result); 10 } 11 finally 12 { 13 db.Close(); 14 } 15 }
QueryExample.vb: RetrieveAllPilots
01Public Shared Sub RetrieveAllPilots() 02 Dim db As IObjectContainer = Db4oFactory.OpenFile(Db4oFileName) 03 Try 04 Dim query As IQuery = db.Query() 05 query.Constrain(GetType(Pilot)) 06 Dim result As IObjectSet = query.Execute() 07 ListResult(result) 08 Finally 09 db.Close() 10 End Try 11 End Sub

Basically, we are exchanging our 'real' prototype for a meta description of the objects we'd like to hunt down: a query graph made up of query nodes and constraints. A query node is a placeholder for a candidate object, a constraint decides whether to add or exclude candidates from the result.

Our first simple graph looks like this.

We're just asking any candidate object (here: any object in the database) to be of type Pilot to aggregate our result.

To retrieve a pilot by name, we have to further constrain the candidate pilots by descending to their name field and constraining this with the respective candidate String.

QueryExample.cs: RetrievePilotByName
1public static void RetrievePilotByName(IObjectContainer db) 2 { 3 IQuery query = db.Query(); 4 query.Constrain(typeof(Pilot)); 5 query.Descend("_name").Constrain("Michael Schumacher"); 6 IObjectSet result = query.Execute(); 7 ListResult(result); 8 }
QueryExample.vb: RetrievePilotByName
1Public Shared Sub RetrievePilotByName(ByVal db As IObjectContainer) 2 Dim query As IQuery = db.Query() 3 query.Constrain(GetType(Pilot)) 4 query.Descend("_name").Constrain("Michael Schumacher") 5 Dim result As IObjectSet = query.Execute() 6 ListResult(result) 7 End Sub

What does 'descend' mean here? Well, just as we did in our 'real' prototypes, we can attach constraints to child members of our candidates.

So a candidate needs to be of type Pilot and have a member named 'name'that is equal to the given String to be accepted for the result.

Note that the class constraint is not required: If we left it out, we would query for all objects that contain a 'name' member with the given value. In most cases this will not be the desired behavior, though.

Finding a pilot by exact points is analogous.We just have to cross the Java primitive/object divide.

QueryExample.cs: RetrievePilotByExactPoints
1public static void RetrievePilotByExactPoints(IObjectContainer db) 2 { 3 IQuery query = db.Query(); 4 query.Constrain(typeof(Pilot)); 5 query.Descend("_points").Constrain(100); 6 IObjectSet result = query.Execute(); 7 ListResult(result); 8 }
QueryExample.vb: RetrievePilotByExactPoints
1Public Shared Sub RetrievePilotByExactPoints(ByVal db As IObjectContainer) 2 Dim query As IQuery = db.Query() 3 query.Constrain(GetType(Pilot)) 4 query.Descend("_points").Constrain(100) 5 Dim result As IObjectSet = query.Execute() 6 ListResult(result) 7 End Sub