How to dynamically build and store complex linq queries against a list of hierarchical objects?

c# dynamic-linq linq linq-to-objects

Question

I have a list of objects in a hierarchical structure. I want to build complex LINQ queries against that object list based on "conditions" a client company sets and are stored in the database. So I need to build these at run time, but because they will be run repeatedly whenever the client's users update or refresh their data I would like to store the LINQ queries in objects rather than rebuild them each time.

I have looked at ScottGu's Blog about Dynamic LINQ.
Also this article about using expression trees.
Neither of these appear to provide an adequate solution, but I may not be understanding them adequately. I'm afraid that I'm trying to use LINQ when I should consider other options.

My object hierarchy:

WorkOrder[]
    Field[]
    Task[]
        Field[]

Here is an example of a LINQ query that I would like to store and execute. I can reasonably build this format based on the database records that define the conditions.

var query =
from wo in WorkOrders
from woF in wo.Fields
from task in wo.Tasks
from taskF in task.Fields
from taskF2 in task.Fields
where woF.Name == "System Status"
    && woF.Value.Contains("SETC")
    && taskF.Name == "Material"
    && taskF.Value == "Y"
    && taskF2.Name == "Planner"
    && taskF2.Value == "GR5259"
select new
{
    wo_id = wo.ID,
    task_id = task.ID
};

A few considerations.

  • Depending on the complexity of the user defined conditions I may or may not need to pull from the different object lists: the "froms" are dynamic.
  • Note that in this example I pulled twice from the task.fields[] so I aliased it two times.
  • The example LINQ structure allows me to have complex ANDs, ORs, parenthesis, etc. that I don't believe is practical with Dynamic Chaining or Expression Trees.

In my code I envision:

//1) Retrieve business rules from DB. I can do this.

//2) Iterate through the business rules to build the linq queries.
foreach (BusinessRule br in BusinessRules) {
    //Grab the criteria for the rule from the DB. 

    //Create a linq to object query based on the criteria just built.
    //Add this query to a list for later use.
}

...Elsewhere in application.

//Iterate through and execute the linq queries in order to apply business rules to data cached in the application.
foreach (LinqQuery q in LinqQueries) {
    //Execute the query

    //Apply business rule to the results.
}

Thank you very much for your thoughts, effort and ideas.

1
2
3/30/2017 9:13:24 PM

Popular Answer

Based on the discussion with Guillaume I would only suggest to pay attention to the type of the resulting query when playing around with advanced dynamic query generation. If you are changing the shape of what is being returned via Select, Aggregate, or one of the other methods you will expect your inner type to change accordingly. If you are just filtering with Where you can keep adding on as many additional cases you want unless you want OR behavior then things like PredicateBuilder helps. If you want to pull in more data via Join, Zip, ... then you are either doing so to filter, add to the rows returned, and possibly change the shape of the data.

I've done a lot of this in the past and had most success focusing on specific helper methods that allow for common cases that I need and then leaning on linq expression trees and patterns such as the visitor pattern to allow custom expression built at runtime.

0
8/21/2017 4:22:24 AM


Related Questions





Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow