4
\$\begingroup\$

I have method which checks period and return schedules:

public IEnumerable<EventSchedule> GetSchedulesForPeriod(PeriodEvent period, string tab = "")
        {
            switch (period)
            {
                case PeriodEvent.Today:
                    return GetTodaySchedules(tab);

                case PeriodEvent.Tomorrow:
                    return GetTomorrowSchedules(tab);

                case PeriodEvent.Week:
                    return GetWeekSchedules(tab);

                case PeriodEvent.FewWeek:
                    return GetFewWeekSchedules(tab);

                case PeriodEvent.Month:
                    return GetMonthSchedules(tab);
                case PeriodEvent.All:
                    return GetAllFromTodaySchedules(tab);

                default:
                    return GetTodaySchedules(tab);
            }
        }

Consider the GetTodaySchedules and GetTomorrowSchedules:

    private IEnumerable<EventSchedule> GetTodaySchedules(string tab)
{
    var today = DateTime.Now.Date;

    var result = Database.EventSchedules.Where(s => s.RecurrenceStart.Value.Date <= today &&
         s.RecurrenceEnd.Value.Date >= today &&
         s.BaseEvent.IsApproved.Value && !s.IsRemoved.Value &&
         s.BaseEvent.EventsCategories.Any(
         c => c.EventCategory.Name == tab)).ToList();

    return result.Where(s => Evaluator.CheckDate(s, today)).ToList();
} 
private IEnumerable<EventSchedule> GetTomorrowSchedules(string tab)
{
    var today = DateTime.Now.AddDays(1).Date;
    var result = Database.EventSchedules.Where(s => s.RecurrenceStart.Value.Date <= today &&
         s.RecurrenceEnd.Value.Date >= today &&
         s.BaseEvent.IsApproved.Value && !s.IsRemoved.Value &&
         s.BaseEvent.EventsCategories.Any(
         c => c.EventCategory.Name == tab)).ToList();

    return result.Where(s => Evaluator.CheckDate(s, today)).ToList();
}

The similar code have all methods above. How to rewrite it? May be, there is some pattern for this? And, the second, now I want that tab checks only if it filled and introduce new var called placeName (also check if filled):

private IEnumerable<EventSchedule> GetTodaySchedules(string tab, string placeName)
    {
        var today = DateTime.Now.Date;

        var result = Database.EventSchedules.Where(s => s.RecurrenceStart.Value.Date <= today &&
             s.RecurrenceEnd.Value.Date >= today &&
             s.BaseEvent.IsApproved.Value && !s.IsRemoved.Value &&
             s.BaseEvent.EventsCategories.Any(
             c => c.EventCategory.Name == tab) && s.BasePlace.Name).ToList();

        return result.Where(s => Evaluator.CheckDate(s, today)).ToList();
    } 

I don't want to create separate methods for this. What is best way to do this?

Thanks.

\$\endgroup\$
1
  • \$\begingroup\$ The current question title, which states your concerns about the code, applies to too many questions on this site to be useful. The site standard is for the title to simply state the task accomplished by the code. Please see How do I ask a good question?. \$\endgroup\$
    – BCdotWEB
    Jan 31, 2021 at 16:58

2 Answers 2

4
\$\begingroup\$

You can compose query predicates by applying several where clauses in a row. The predicates must be passed as Expression<Func<T, bool>> for composition.

See LINQ to Entities: Combining Predicates on Microsoft Docs.

Create a general schedules query like this

private IEnumerable<EventSchedule> GetSchedules(
    string tab,
    Expression<Func<EventSchedule, bool>> dateCondition)
{ 
    var result = Database.EventSchedules
        .Where(s => s.BaseEvent.IsApproved.Value &&
            !s.IsRemoved.Value &&
            s.BaseEvent.EventsCategories.Any(c => c.EventCategory.Name == tab))
        .Where(dateCondition)
        .ToList();
    return result.Where(s => Evaluator.CheckDate(s, today)).ToList();
}

And then pass it the appropriate individual date predicate like this

private IEnumerable<EventSchedule> GetTodaySchedules(string tab) {
    var today = DateTime.Now.Date;
    return GetSchedules(
        tab,
        s => s.RecurrenceStart.Value.Date <= today &&
             s.RecurrenceEnd.Value.Date >= today);
}

private IEnumerable<EventSchedule> GetTomorrowSchedules(string tab) {
    var tomorrow = DateTime.Now.AddDays(1).Date;
    return GetSchedules(
        tab,
        s => s.RecurrenceStart.Value.Date <= tomorrow &&
             s.RecurrenceEnd.Value.Date >= tomorrow);
}
\$\endgroup\$
3
\$\begingroup\$

Just add another argument to the method:

private IEnumerable<EventSchedule> GetSchedules(string tab, DateTime day)
{
    var result = Database.EventSchedules.Where(s => s.RecurrenceStart.Value.Date <= day &&
         s.RecurrenceEnd.Value.Date >= day &&
         s.BaseEvent.IsApproved.Value && !s.IsRemoved.Value &&
         s.BaseEvent.EventsCategories.Any(
             c => c.EventCategory.Name == tab)).ToList();

    return result.Where(s => Evaluator.CheckDate(s, day)).ToList();
}

And call it with an appropriate value for day. Easy, no?

\$\endgroup\$
3
  • \$\begingroup\$ Additionally properties can be made to get the appropriate days. Today returns DateTime.Today.Date, Tomorrow returns DateTime.Tomorrow.AddDays(1).Date, etc. Though I'd make the day parameter first. That way calls to the method could look like: GetSchedules(Today, tab) \$\endgroup\$ Apr 26, 2012 at 14:04
  • \$\begingroup\$ There is more complex queries( RecurrenceStart and RecurrenceEnd) \$\endgroup\$
    – user348173
    Apr 26, 2012 at 15:49
  • \$\begingroup\$ @user348173 Well you didn’t show them. But doesn’t matter, the same principle can be applied: just provide the parts that vary as arguments to the method. \$\endgroup\$ Apr 26, 2012 at 16:07

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.