Not sure if this is entirely possible; I’ve found some stuff about expression and predicate builders, but so far nothing that lets you run arbitrary queries without knowing them in advance.
Basically, I have a collection of objects from a large SQL database, and I’m building a webpage (ASP.NET MVC 4) to allow a user to display and filter these objects. The queries the users will be entering will vary in complexity. The simplest and neatest way to let them enter these queries is something like the way the Visual Studio TFS plugin lets you search work items: a table of conditions, where you can keep adding rows. You select “and” or “or” for the join condition, then select a field, enter a value, and select whether you want things that do or do not match it:
1. show items where [Field] [is|is not] [value]
2. [and|or] [Field] [is|is not] [value]
3. [and|or] [Field] [is|is not] [value]
etc...
What’s the simplest way to turn that into something LINQ-ish that I can stick a .ToList() on the end of? The only solution I’ve come up with so far has involved a rather large and ugly switch block with cases to match the various fields and tack on a .Where(), but to allow the user to select “or” for a condition then I end up doing something like this:
- While condition is AND:
- use big switch to match the field
query = query.Where(ThisField == value);
- When you hit a condition that is OR:
- append current results to temporary list
- new query from full unfiltered list
- use big switch to match the field
query = fullList.Where(ThisField == value);- continue as before
- When you run out of conditions, append your current result set to the temporary list you’ve been using all along, and return that list.
This seems less elegant than I’d like.
You can do it like this:
This assumes you have a class as a model of the database row with the correct types. You can then parse your conditions into a list of the typed condition shown above via regex and the provided code can convert that to an expression tree. The resulting expression can either be compiled and run (as shown) or converted to SQL (just stuffing the predicate into the IQueryable.Where instead).