I read a fantastic blog article from Nick Blumhardt yesterday which kicked off some crazy ideas in my head.
With the following class, I can query on IsOverdue using linq... but not using linq to sql (or linq to nhibernate). How frustrating!
This is a fundamental issue in relational to object mapping systems, but we can fix it using some linq trickery.
I think my solution is very cool, but I'm not sure how acceptable it is for a production environment.
Please leave feedback if you like it / makes you want to vomit.
Let's modify the Loan class implementation of IsOverdue:
Here we move the logic for IsOverdue into a separate QueryProperty member that takes care of the nasty details.
Hopefully you'll agree that the code is still fairly readable, and encapsulated with all the logic still bundled inside the Loan class.
By moving this logic into a lambda expression, we can now write queries for both database and object collections! e.g
When coding these query properties it can be very handy to reference other query properties. e.g.
This allows us to create very complicated queries in a very simple manner.
Too good to be true? You're right; there's a devil in the details.
You might have picked it up already - how does linq interpret my query property correctly?
By modifying the expression tree!
My Repository class implements the Where() and translates the expression; replacing any QueryProperty references with a call to the actual lambda expression.
The really ugly part is that it's a string based lookup ie. "<name>Property". Though I also check the type to be extra safe.
It's really not a bad trade off, considering it's very similar to how WPF DependencyProperty's work.
This is a really easy and seamless way to implement custom queryable properties in your domain objects.
I've only touched on a fraction of the possibilities with this technique, but it shows the power and flexibility of linq.
Make sure you check out the sample application for the full code.
ed: Continue to Part II