Reputation: 43
Illustration of database (actual column and table name is different)
EmployeeeID IsSicked IsRetired IsHoliday
1 false false true
2 true false true
3 true true true
4 false false false
What problem am I having?
I have a checkbox for IsSicked, IsRetired and IsHoliday in my application, which allow user to check multiple selection and submit.
The system will return list of employee from database based on the selection of user. For example, when user tick IsSicked and IsRetired, system will return list of user who is sicked and is retired from database.
Based on below code, I need to write 2^3 = 8 possibilities to get the result. As the column expand to n columns(exluding employeeID column), I will need to write 2^n if else statement to get the query. If there are 10 column (10 checkboxes selection), then i need to write 2^10 = 1024 if else statement
It seems to me that this supposed to be quite a common problem faced by developers, unfortunately i can't find a good solution to this online
Expectation of solution
Generic combination of C# code and/or LINQ query that no need hard code the logic as below if(...) else if (...)
var employee = db.Employee.AsQueryable():
if(model.IsSicked == true)
{
employee.Where(z => z.IsSicked == true)
}
else if(model.IsRetired == true)
{
employee.Where(z => z.IsRetired == true)
}
...
...
else if(model.IsSicked == true && model.IsRetired == true)
{
employee.Where(z => z.IsSick == true || z.IsRetired == true)
}
else if (model.IsSicked == true && model.IsRetired == true && model.IsHoliday == true)
{
employee.Where(z => z.IsSick == true || z.IsRetired == true || z.IsHoliday == true)
}
Upvotes: 2
Views: 1442
Reputation: 28097
Why not use a enum
with [Flags]
:
[Flags]
public enum EmployeeStatus
{
None = 0,
Sick = 1,
Retired = 2,
Holiday = 4
}
In your database you can store this as an integer.
Your model becomes similar to
public class Employee
{
public int Id { get; set; }
public EmployeeStatus Status { get; set }
}
then LINQ queries become similar to:
employee.Where(z => z.Status == EmployeeStatus.Sick)
Because of using [Flags]
you can do the following for multiple states, e.g. sick and retired:
employee.Where(z => z.Status == (EmpoyeeStatus.Sick | EmployeeStatus.Retired))
Please note that |
is the boolean OR which translates in the following:
EmpoyeeStatus.Sick | EmployeeStatus.Retired
= 1 | 2
= b01 | b10
= b11
= 3
so effectively works as "and" in our logic.
Upvotes: 3
Reputation: 118937
You can build up your Where predicate like this:
var employee = db.Employee.AsQueryable():
if(model.IsSicked == true)
employee = employee.Where(z => z.IsSicked == true)
if(model.IsRetired == true)
employee = employee.Where(z => z.IsRetired == true)
if (model.IsHoliday == true)
employee = employee.Where(z => z.IsHoliday == true)
Alternatively, you could do this:
employee.Where(z => (z.IsSicked || !model.IsSicked) &&
(z.IsRetired || !model.IsRetired) &&
(z.IsHoliday || !model.IsHoliday))
Upvotes: 0
Reputation: 4051
You can use library called LINQKit and use its PredicateBuilder to create predicate with dynamic ORs.
var employee = db.Employee.AsQueryable():
var predicate = PredicateBuilder.False<Employee>();
if (model.IsSicked == true)
predicate = predicate.Or(p => p.IsSick == model.IsSick);
if (model.IsRetired == true)
predicate = predicate.Or(p => p.IsRetired == model.IsRetired);
if (model.IsHoliday == true)
predicate = predicate.Or(p => p.IsHoliday == model.IsHoliday);
var result = employee.AsExpandable().Where(c => predicate.Invoke(c)).ToList()
Upvotes: 0