I'm writing a method which returns a collection of ProductPeriod
objects based on the following filters:
DateTime? from
DateTime? to
bool? includeActive
bool? includeInactive
The ProductPeriod
object looks like this:
public class ProductPeriod
{
public int Id { get; set; }
public string Name
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public bool IsActive { get; set; }
}
So the idea is, that the client can select a to date and/or a from date and/or include active periods and/or include inactive periods. This gives quite a lot of scenarios for the filtering which makes for quite a large method, which I started writing (and didn't finish yet):
public IEnumerable<ProductPeriod> GetFilteredProductPeriods(DateTime? from, DateTime? to, bool? includeActive, bool? includeInactive)
{
// 1. from date only
if(from.HasValue && to == null && includeActive == null && includeInactive == null)
return _entities.ProductPeriods.Where(x => x.StartDate >= from.Value).ToList();
// 2. from and to date
if(from.HasValue && to.HasValue && includeActive == null && includeInactive == null)
return _entities.ProductPeriods.Where(x => x.StartDate >= from.Value && x.EndDate <= to.Value).ToList();
// 3. to date only
if (to.HasValue && from == null && includeActive == null && includeInactive == null)
return _entities.ProductPeriods.Where(x => x.EndDate <= to.Value).ToList();
// 4. from date and show active
if (from.HasValue && (includeActive != null && includeActive.Value) && to == null && includeInactive == null)
return _entities.ProductPeriods.Where(x => x.StartDate >= from.Value && x.IsActive).ToList();
// 5. from, to and show active
if (from != null && to != null && (includeActive != null && includeActive.Value) && includeInactive == null)
return _entities.ProductPeriods.Where(x => x.StartDate >= from.Value && x.EndDate <= to.Value && x.IsActive).ToList();
// 6. to date and show active
if (to.HasValue && (includeActive != null && includeActive.Value) && from == null && includeInactive == null)
return _entities.ProductPeriods.Where(x => x.EndDate <= to.Value && x.IsActive).ToList();
// 7. .... and so on, so forth..
}
I'm wondering if there's a better/smarter way to do this, that I'm not aware of? I.e. some kind of generic way? :-)
Thanks in advance.
Yes, there's definitely a better way. You should use the way that queries can be built up in LINQ:
public IEnumerable<ProductPeriod> GetFilteredProductPeriods
(DateTime? from, DateTime? to, bool? includeActive, bool? includeInactive)
{
IQueryable<ProductPeriod> query = _entities.ProductPeriods;
if (from != null)
{
query = query.Where(x => x.StartDate >= from.Value);
}
if (to != null)
{
query = query.Where(x => x.EndDate >= to.Value);
}
if (includeActive == false)
{
query = query.Where(x => !x.IsActive);
}
if (includeInactive == false)
{
query = query.Where(x => x.IsActive);
}
return query.ToList();
}
Note that setting includeInactive=false
and includeActive=false
will give you no results... you might want to change it to a single parameter which is false
(only inactive), true
(only active), null
(all).
See more on this question at Stackoverflow