Reputation: 2523
I need to query database and filter based on parameters passed into the function. I am passing two date parameters (used as a date range), a name, and a status parameters. All the parameters can have 'and' or 'or' conditions. Basically, I would like to build an linq expression based on which parameters are populated and pass it to Entity Framework to return a result set.
How can I do this with minimum 'if' statements? If you could be kind enough to provide an explanation with your example code, that would be awesome. I am trying to learn expression trees so an explanation would help.
At this point I don't have much code. That is why I have posted here. I can list the method signature. What exactly are you looking for?
public enum EmployeeStatus
{
FullTime,
PartTime,
Contract
}
public IEnumerable<Employee> FilterEmployees(DateTime? startDate,
DateTime? endDate, string employeeName, EmployeeStatus employeeStatus)
{ }
Upvotes: 0
Views: 706
Reputation: 2316
All the parameters can have 'and' or 'or' conditions. - you could consider using the PredicateBuilder. See http://www.albahari.com/nutshell/predicatebuilder.aspx. Why? Because this allows you to write a single query, but add an AND/OR predicate only if it is needed. You may or may not require this feature, but it is a good feature to be aware of. There is no database overhead until the query is actually called - it provides a means to conditionally build an IQueryable where you may not want to match against fields under certain conditions. E.g. I used this the other day to ignore a product code field - with min-length 10 - on searches where the input string was less than 10 characters.
This will allow you to add AND/OR statements using an if-condition like so:
public IQueryable<Employee> FilterEmployees(IQueryable<Employee> query, DateTime startDate, DateTime endDate, string employeeName, EmployeeStatus employeeStatus)
{
var predicate = PredicateBuilder.True<Employee>();
//All names starting with 'A'
predicate = predicate.And(x => x.Name.StartsWith("A"));
//Add a condition only if the employee is PartTime
if (employeeStatus == EmployeeStatus.PartTime)
{
//Add condition for when they start
predicate = predicate.And(x => x.StartDate >= startDate);
}
else
{
//Say we don't care about the start date for the other employee statuses,
//but we want to add condition for when non-part-time employees are due to leave
predicate = predicate.And(x => x.EndDate <= endDate);
//or their name ends in 'z'
predicate = predicate.Or(x => x.Name.EndsWith("z"));
}
IQueryable<Employee> employees = query.FindBy(predicate); //you should probably use a repository here to return your query
return employees
}
Note - this is intended as psuedo-code to demonstrate and may have errors - see the above link for the proper implementation.
Upvotes: 2
Reputation: 329
public IQueryable<Employee> FilterEmployees(IQueryable<Employee> query, DateTime? startDate, DateTime? endDate, string employeeName, EmployeeStatus employeeStatus)
{
if (startDate != null)
query = query.Where(x => x.StartDate >= startDate);
// etc...
return query;
}
Upvotes: 4