tags:

views:

168

answers:

1

I know the following is possible with linq2db4o

from Apple a in db
where a.Color.Equals(Colors.Green)
select a

What I need however is something that allows me to build my query conditionally (like I can in other linq variants)

public IEnumerable<Apple> SearchApples (AppleSearchbag bag){
    var q = db.Apples;
    if(bag.Color != null){
        q = q.Where(a=>a.Color.Equals(bag.Color));
    }
    return q.AsEnumerable();
}

In a real world situation the searchbag will hold many properties and building a giant if-tree that catches all possible combinations of filled in properties would be madman's work.

It is possible to first call

var q = (from Color c in db select c);

and then continue from there. but this is not exactly what I'm looking for.

Disclaimer: near duplicate of my question of nearly 11 months ago.
This one's a bit more clear as I understand the matter better now and I hope by now some of the db4o dev eyes could catch this on this:

Any suggestions?

+5  A: 

Yes it's definitely possible to compose optimized LINQ queries using db4o. Granted that db is defined as follows:

IObjectContainer db;

Here is your query:

public IEnumerable<Apple> SearchApples (AppleSearchbag bag)
{
    var query = db.Cast<Apple> ();
    // query will be a Db4objects.Db4o.Linq.IDb4oLinqQuery<Apple>
    if (bag.Color != null)
        query = query.Where (a => a.Color == bag.Color);

    return query;
}

In that case, the query will be executed whenever the returned enumerable is being iterated over.

Another possibility is to use the IQueryable mechanism, that has the advantage of being better recognized by developers:

public IQueryable<Apple> SearchApples (AppleSearchbag bag)
{
    var query = db.AsQueryable<Apple> ();
    // query will be a System.Linq.IQueryble<Apple>
    if (bag.Color != null)
        query = query.Where (a => a.Color == bag.Color);

    return query;
}

In both cases, db4o will try to deduce an optimized query from the lambda expression upon execution, and if it fails, will fallback to LINQ to objects. The first one has the advantage of being more direct, by avoiding the queryable to LINQ to db4o transformation.

Jb Evain
Brilliant. Exactly what I was looking for :D
borisCallens
Although I tried the AsQueryable option, but the method doesn't seem to exist on the IObjectContainer. Does this method reside anywhere else then in the Db4objects.Db4o.Linq?
borisCallens
Are you using the latest version of db4o? It's definitely there. Although it's defined on ISodaQueryFactory, but IObjectContainer extends this interfaces. You just have to add a using directive for Db4objects.Db4o.Linq.
Jb Evain
I referenced Db4objects.Db4o.Linq and Db4objects.Db4o v7.4.121.14026;I then have IObjectContainer db = server.OpenClient();db.Cast is there, but no db.AsQueryAble.
borisCallens
*db.AsQueryable
borisCallens
Maybe it's not available in 7.4, but it's definitely available in the development release (7.12).
Jb Evain