Sometimes the capabilities of regular SODA-queries is not enough. In such cases you can add evaluations to the SODA-query. A evaluation is a piece of code which runs against objects.
To use a evaluation, you need to pass an instance of the IEvaluation-interface as a constrain. db4o will call the match-method of that interface. Implement the match-method of the IEvaluation-interface. In the match-method you can get the candidate-object and the object-container. Compare the object and when it matches, pass true to the include-method. Otherwise pass false.
While SODA evaluations are extremely powerful they are also slow. In order to run the evaluation the objects need to be instantiated from the database and then processed by the evaluator. This means that you should use evaluations only when there's no other possibility.
Here's an example for a simple evaluation. This evaluation filters pilots by the age and picks only pilots with an odd-number as age.
First we need to create the evaluation-class:
class OnlyOddAge : IEvaluation { public void Evaluate(ICandidate candidate) { Pilot pilot = (Pilot)candidate.GetObject(); candidate.Include(pilot.Age % 2 != 0); } }
Class OnlyOddAge Implements IEvaluation Public Sub Evaluate(ByVal candidate As ICandidate) _ Implements IEvaluation.Evaluate Dim pilot As Pilot = DirectCast(candidate.GetObject(), Pilot) candidate.Include(pilot.Age Mod 2 <> 0) End Sub End Class
After that, you can use the evaluation in the SODA-query. An evaluation is added as a regular constrain.
IQuery query = container.Query(); query.Constrain(typeof (Pilot)); query.Constrain(new OnlyOddAge()); IObjectSet result = query.Execute();
Dim query As IQuery = container.Query() query.Constrain(GetType(Pilot)) query.Constrain(New OnlyOddAge()) Dim result As IObjectSet = query.Execute()
It's also possible to use the evaluation on a certain field. For this you descend into the field on which the evaluation should be applied. After that, specify the evaluation as a constrain on that field.
IQuery query = container.Query(); query.Constrain(typeof (Car)); query.Descend("pilot").Constrain(new OnlyOddAge()); IObjectSet result = query.Execute();
Dim query As IQuery = container.Query() query.Constrain(GetType(Car)) query.Descend("pilot").Constrain(New OnlyOddAge()) Dim result As IObjectSet = query.Execute()
Evaluation also allow you to add very specific additional query capabilities. On of the most useful ones is regular expressions. First create a regular expression evaluation:
class RegexConstrain : IEvaluation { private readonly Regex pattern; public RegexConstrain(String pattern) { this.pattern = new Regex(pattern); } public void Evaluate(ICandidate candidate) { string stringValue = (string)candidate.GetObject(); candidate.Include(pattern.IsMatch(stringValue)); } }
Class RegexConstrain Implements IEvaluation Private ReadOnly pattern As Regex Public Sub New(ByVal pattern As [String]) Me.pattern = New Regex(pattern) End Sub Public Sub Evaluate(ByVal candidate As ICandidate) _ Implements IEvaluation.Evaluate Dim stringValue As String = DirectCast(candidate.GetObject(), String) candidate.Include(pattern.IsMatch(stringValue)) End Sub End Class
After that you can use it on any string field:
IQuery query = container.Query(); query.Constrain(typeof (Pilot)); query.Descend("name").Constrain(new RegexConstrain("J.*nn.*")); IObjectSet result = query.Execute();
Dim query As IQuery = container.Query() query.Constrain(GetType(Pilot)) query.Descend("name").Constrain(New RegexConstrain("J.*nn.*")) Dim result As IObjectSet = query.Execute()