99823
99823

Reputation: 2457

Dynamically Building a List of Func<t,t> - then applying to a linq query

Not sure if this is the best approach, however here are my thoughts

I am using Entity Framework Data Model v 4.1 - i'm trying to build a where statement dynamically so that I dont have to query the db everytime, instead i can build a "list of" conditionals, then apply them all at once so the db is only queryed once as opposed to everytime i add my new conditional - if that makes sense...

here is what i have

List<Func<Order, bool>> orderFunctions = new List<Func<Order, bool>>();
if (this.LoggedInUser.UserId == 9)
{
Func<Order, bool> deleg = o => o.Status.Equals(OrderStatus.NewOrder);
orderFunctions.Add(deleg);
}
else if (this.LoggedInUser.UserId == 22)
{
Func<Order, bool> deleg = o => o.AssignedToUserId.Equals(22);
orderFunctions.Add(deleg);
}
List<Orders> orders = Entities.Orders.Where( Some How Apply my Order Functions List Here ).ToList();

I'm not sure if i'm even taking the right approach here - hopefully this makes sense - any guidance, sample code would be fantastic, i've having a heck of a time finding examples / tutorials for this online

Upvotes: 2

Views: 1530

Answers (2)

Random Dev
Random Dev

Reputation: 52280

Jon gave - of course - the answer how to do this better.

But for your original point, and why this won't work:

It is not dificult to apply the hole list (just do

x => orderFunctions.All(f => f(x))

) but you will not get any SQL-love from this - meaning you will get an error because EF cannot know what to do with the all (or whatever you will code there). You would have to query all entries (with ToList, or ToArray) and after this it would work ... but without performance ;)

Upvotes: 2

Jon Skeet
Jon Skeet

Reputation: 1500785

You can do this just by calling Where multiple times:

IQueryable<Order> query = Entities.Orders;

if (this.LoggedInUser.UserId == 9)
{
    query = query.Where(o => o.Status.Equals(OrderStatus.NewOrder));
}
else if (this.LoggedInUser.UserId == 22)
{
    query = query.Where(o => o.AssignedToUserId.Equals(22));
}

List<Order> orders = query.ToList();

Until you start trying to retrieve the results, it won't contact the database.

If you really want to create a list, you'd need to create a List<Expression<Func<Order, bool>>> - they have to be expression trees rather than delegates, so that the Entity Framework can deal with them. Then you could just do:

foreach (var predicate in predicates)
{
    query = query.Where(predicate);
}

Or you could use PredicateBuilder to build up a single expression tree.

Upvotes: 6

Related Questions