6

I have two dropdownlists in my module.

In one dropdownlist, I have hardcoded all the operators like <,>,<=,>=,==

In second dropdownlist, I have hardcoded salary of employees like 1000,2000,3000,4000....50000

Now if I select < from one list and 2000 from second list and click on submit button I should get list of employees who have salary less than 2000.

I want to do this in asp.net mvc3

How can I accomplish this task? Do I need to write a stored procedure for this?

I have created dropdownlist like:

viewModel.OperatorsList = new[]
{
  new SelectListItem { Value = "<", Text = "<" },
  new SelectListItem { Value = ">", Text = ">" },  
  new SelectListItem { Value = "<=", Text = "<=" },
  new SelectListItem { Value = ">=", Text = ">=" },
  new SelectListItem { Value = "==", Text = "==" }
};

viewModel.SalaryList = new[]
{
  new SelectListItem { Value = "1000", Text = "1000" },
  new SelectListItem { Value = "2000", Text = "2000" },  
  new SelectListItem { Value = "3000", Text = "3000" },

  // and so on
};

and I have used this to show dropdownlist in view:

<%: Html.DropDownListFor(x => x.Operators, Model.OperatorsList)%>
Aleks Andreev
  • 7,016
  • 8
  • 29
  • 37
Keren Caelen
  • 1,466
  • 3
  • 17
  • 38

1 Answers1

6

well, you could do something like that

assuming viewModel is... your viewModel, and you've got an entity Employee with a property Salary (int in this sample, it's probably a decimal in real world)

create a static helper class

public static class MyHelper
    {
        // a dictionary for your operators and corresponding ExpressionType
        public static Dictionary<string, ExpressionType> ExpressionTypeDictionary = new Dictionary<string, ExpressionType>
        {
            {"<", ExpressionType.LessThan},
            {">", ExpressionType.GreaterThan},
            {">=", ExpressionType.GreaterThanOrEqual}
            //etc
        };
        //a method to filter your queryable
        public static IQueryable<Employee> FilterSalary(this IQueryable<Employee> queryable, int salary, string operatorType)
        {
            //left part of the expression : m
            var parameter = Expression.Parameter(typeof(Employee), "m");
            //body is the right part of the expression : m
            Expression body = parameter;
            //m.Salary
            body = Expression.Property(body, "Salary");
            //m.Salary <= 1000 (for example)
            body = Expression.MakeBinary(ExpressionTypeDictionary[operatorType], body, Expression.Constant(salary));
            //m => m.Salary <=1000
            var lambda = Expression.Lambda<Func<Employee, bool>>(body, new[] { parameter });
            //so it will be queryable.Where(m => m.Salary <= 1000)
            return queryable.Where(lambda);
        }
}

usage

var queryable = context.All<Employee>();//or something like that, returning an IQueryable<Employee>
queryable = queryable.FilterSalary(viewModel.Salary, viewModel.Operators);
jaredbaszler
  • 3,941
  • 2
  • 32
  • 40
Raphaël Althaus
  • 59,727
  • 6
  • 96
  • 122
  • Althaus:Thanks for your reply. I understood about the dictionary for operators but confused about the static class FilterSalry that you have suggested. can you please explain me something about this class? – Keren Caelen May 15 '13 at 05:42
  • @K2_Ketu well, the extension method `Where` takes an `Expression>` as parameter. The method is just building this expression, transforming it into a lambda, and passing it to the Where method. You might try to debug and see what's in `body` step by step, and / or google for Expression trees. I'll add some comment in my code too. – Raphaël Althaus May 15 '13 at 07:56
  • @K2_Ketu and FilterSalary is not a class, just a static extension method, like... `Where` – Raphaël Althaus May 15 '13 at 07:59
  • Althaus: Thank you so much. really it is very helpful.now I understand about this. Just little more help. can you please tell me what should be there in `typeof(YourEntity)`. bcoz as u know Employee is my entity – Keren Caelen May 15 '13 at 08:30
  • @K2_Ketu Well seen, it was a typo, I made a more generic version at first and forgot to correct this. Edited. – Raphaël Althaus May 15 '13 at 08:41
  • Althaus: Thank you so so much.. It is a perfect answer :-) – Keren Caelen May 15 '13 at 08:43
  • @Raphaël Althaus, Could you also add function 'Contains', or any user-defined string operation function? I think that maybe useful. – Lei Yang Sep 01 '13 at 13:12
  • 1
    @LeiYang well, Contains, and other methods (so not "comparison operators") requires some other logic (you need reflection to get the methods, and use Expression.Call). You can take a look here : http://stackoverflow.com/questions/14614645/building-expression-tree-for-string-contains – Raphaël Althaus Sep 01 '13 at 16:16