1

I have a LinQ query as below

var filtered=from c in country
         where c.Id>=5
         select c;

Now i need to have the operator '>=' to be dynamic i.e., the operator may be '>=' or '==' or '<=' etc depending on a certain criteria and the query should execute based on that operator. How to achieve this in LinQ?

3
  • I'd rather write new methods or use a switch-case. Commented Jul 19, 2011 at 6:46
  • Can you elaborate more please? Saying that the operator changes based on a certain criteria it would be nice to know what that criteria is - user input, programmatic control, other queried data, etc. What are you trying to do? Commented Jul 19, 2011 at 6:46
  • @Enigmativity: The criteria in my case is user selection. The user selects the different types of operators(>=,<=,==,!=) from a dropdown list. Commented Jul 19, 2011 at 7:08

3 Answers 3

3

You can do it like this:

var filtered = country.AsQueryable();
if(cond == 0)
    filtered = filtered.Where(c => c.Id <= 5);
else if(cond == 1)
    filtered = filtered.Where(c => c.Id >= 5);
else if(cond == 2)
    filtered = filtered.Where(c => c.Id == 5);
Sign up to request clarification or add additional context in comments.

6 Comments

@downvoter: Without a comment, the downvote is not constructive
Depending on the type of 'country', this may not compile. In this case, 'filtered' should be explicitly declared IQueryable< >, rather than implicitly typed.
@devio - What do you mean that it may not compile? How will declaring it IQueryable<> be any better than implicitly typed?
@Enigmativity: implicitly typed means that the type of the variable is the exact type of that variable, e.g. ObjectQuery<Country>. But Where will return the more general type IQueryable<Country>. The assignment of an IQueryable<Country> to an ObjectQuery<Country is illegal. That's why filtered needs to be declared as IQueryable<Country>.
@Daniel - doesn't the .AsQueryable() ensure that it is IQueryable<>?
|
2

I would avoid the "if-then-else" or "switch" methods, and use a "dictionary" instead.

I assume you have a control that allows the user to select the number (ie 5) too, so you would need a way to "dynamically" add this to the query too.

Define this dictionary:

var filters = new Dictionary<string,
    Func<IQueryable<Country>, int, IQueryable<Country>>>()
{
    { ">", (cs, n) => cs.Where(c => c.Id > n) },
    { ">=", (cs, n) => cs.Where(c => c.Id >= n) },
    { "==", (cs, n) => cs.Where(c => c.Id == n) },
    { "<=", (cs, n) => cs.Where(c => c.Id <= n) },
    { "<", (cs, n) => cs.Where(c => c.Id < n) },
};

Now you can populate your drop-down with the keys from the dictionary and then you can easily get your query out by doing this:

country = filters[">"](country, 5);

Or maybe something like this:

country = filters[dd.Value](country, int.Parse(tb.Text));

Yell out if you'd like any further explanation.

2 Comments

it would be nice if you could accept this answe as your solution so others with the same problem can easily find it @Abilash
@JohnnyCageWins - it would be nice, wouldn't it... :-)
0

This is not exactly what you want, however I think doing what you say is not safe and it is bad for readibility and not reusable.For those purposes I always try to use new methods and be void on them.

 public void static FilterById(int limit, string condition, IEnumerable filter, Type country)
 {  
    var countryQueryable = country.AsQueryable();//Edit inspired by devio's comment on  Mr.Hilgarth's answer. 

    switch(condition)
   {
      case(">") :
      {
        filter = countryQueryable .Where(q=>q.Id > 5)
        break;
       } 
       case(">=") :
       {
         filter = countryQueryable .Where(q=>q.Id >= 5)
         break;
        } 
        case("=") :
        {
          filter = countryQueryable .Where(q=>q.Id == 5)
          break;
         } 
        case("<=") :
        {
          filter = countryQueryable .Where(q=>q.Id <= 5)
          break;
         } 
         case("<") :
         {
          filter = countryQueryable .Where(q=>q.Id < 5)
          break;
         } 
     }
}

EDIT: Dynamic LINQ (Part 1: Using the LINQ Dynamic Query Library) might help a bit.

2 Comments

@Daniel Hilgarth,@JohnnyCageWins: Thanks for the replies. I know to use an if..else or select..case for this scenario. I need to minimize the code by doing something else from the above mentioned techniques.So, is there any other possibilities?
I am going to add a link to my answer, however I really think what you want to do will make you suffer later. @Abilash

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.