tags:

views:

172

answers:

2

How do you do it?

I sit here and trying to make things simpler for myself and others. But I can't seem to decide what way would be the best. The issue is this:

Start with a collection of something from a data context, and then start filtering out on a whole bunch of different criterias. If this, then those or perhaps those unless that is not this but that and between those and over the hill except if nothing then backwards, up and beyond.

Ok, maybe not that complex... but I basically need to build up trees like these:

        start
          |
          x
          |
          x
         / \
        x   x
        |   |
        x   x
         \ /
          x
         / \
        x   x
        |   |
        x   |
        |   |
        x   x
         \ /
          x
          |
        result

Where | represents And and the branches represents Or. Because of the Or alternative paths I can't use data.Where(...).Where(...).Where(...) all the way through. And using things like Union and Concat have a tendency to crash (actually haven't managed to use it in a working way yet). In other words I have to build up Expression<Func<T, bool>> instances.

I have created extension methods for adding those together with AndAlso and OrElse (With lots of help from Marc. I have started to create a predicate builder class to make things even a bit more simpler. Plan is to create chains of And-stuff, and then Or them together... kind of... :p

Anyways, I just can't decide if these are good ideas or not. I think the road I have started down now, probably can end up with an ok "working environment" for me when I am coding these chains. But I am curious to know how others are solving these issues. Which I would think may be pretty common, at least in applications that have to filter and crunch data in all kinds of weird ways and then display them to the user.

+1  A: 

Some people swear by Predicate Builder. Personally, I've always found it sufficient to mangle the Expressions manually - but maybe I'm just odd like that (and besides, I've been playing with the Expression API for quite a while). But as long as you have suitable unit tests in place, I can't see any issue with this approach. The biggest current gripe would be EF's limited support for Expression.Invoke - rest assured, that'll be one of the first things I check when 4.0 goes "beta".

Marc Gravell
Yeah, my PredicateBuilder is kind of based on that albahari nutshell builder thing. I read the thing about EF Invoke stuff in your blog... but hopefully that will be fixed... Not a problem for me now though, since we use Linq2Sql.
Svish
By "mangle the Expressions manually", do you mean doing stuff like doing all that ParameterExpression; BinaryExpression = AndAlso(Invoke, Invoke); Lambda( ... ); stuff for each item in the chains? Or do you use extension methods?
Svish
I tend to keep things tightly scoped and use Expression.Invoke, so I am only doing one logical thing at a time... you can of course build a single highly complex chain, but I find that harder to debug.
Marc Gravell
+1  A: 

It's not especially clean to look at, and would probably get uglier if it was a very complex situation, but for simple stuff I sometimes build queries like this

string MinOrMaxOption = "min";
int CompareValue = 5;
var Results = from row in MyData
              where (MinOrMaxOption=="min" && row.ValueA > CompareValue)
              || (MinOrMaxOption=="max" && row.ValueA < CompareValue)
              select row;

This of course only works if the query possibilities are predefined. I don't know if that's the case in your example or not.

GeekyMonkey
yeah, that could end up becoming quite ugly yes... but for simple things, then yes, possibly =)
Svish