Linq到实体日期部件优化

时间:2015-03-27 14:53:40

标签: c# sql-server-2008 linq-to-sql linq-to-entities entity-framework-6

我正在尝试根据网站管理信息中心的日期字段的一部分创建明细(来自时间间隔分析图表)。

Dashboard Charts

Drilldown

var drilldownQuery = DataManager.DataSessions
            .Include("Location")
            .Include("Quote.Carriers")
            .Include("Drivers")
            .Include("Vehicles")
            .Where(session =>
                session.Timestamp >= Model.FromDate &&
                session.Timestamp < through
            );

        if (!String.IsNullOrWhiteSpace(Model.DrillDown))
        {
            drilldownQuery = drilldownQuery.ToList()
                .Where(session => 
                   IntervalSelector(session) == Model.DrillDown);
        }

    public string IntervalSelector(DataSession session)
    {
        switch (Model.SelectedInterval)
        {
            case TimeInterval.Hourly:
                return session.Timestamp.Hour.ToString("D2");
            case TimeInterval.Weekday:
                return ((int)session.Timestamp.DayOfWeek).ToString();
            case TimeInterval.Weekly:
                return session.Timestamp.Date.AddDays(-(int)session.Timestamp.DayOfWeek).ToString("yyyy/MM/dd");
            case TimeInterval.Monthly:
                return session.Timestamp.Date.ToString("yyyy/MM");
            case TimeInterval.Annual:
                return session.Timestamp.Year.ToString("D4");
            default:
                return session.Timestamp.Date.ToString("yyyy/MM/dd");
        }
    }

当然,大日期范围的表现非常糟糕。我希望避免“ToList()”调用,以便在数据库而不是内存中执行向下钻取标准。这就是我被困住的地方,特别是在深入了解每小时和工作日的标准时。

IntervalSelector还用于对图形查询和向下钻取进行分组。我愿意使用单独的选择器来进行深入研究,无论什么都能提高它的性能。图形查询也执行ToList,但性能很好,因为它不需要包含。

var graphQuery = DataManager.DataSessions
            .Where(session =>
                session.Timestamp >= Model.FromDate &&
                session.Timestamp < through);

我想更好的方法是将switch语句移到Linq之外,如下所示:

switch (Model.SelectedInterval)
{
    case TimeInterval.Hourly:
        int selectedHour = int.Parse(Model.DrillDown);
        drilldownQuery = drilldownQuery
            .Where(session => session.Timestamp.Hour == selectedHour);
        // thoughts on this? any better way?
        break;
    case TimeInterval.Weekday:
        var selectedWeekday = int.Parse(Model.DrillDown) + 1; 
             // convert to sql dayofweek (Sun = 1)
        drilldownQuery =
            drilldownQuery.Where(
                 session => SqlFunctions
                      .DatePart("weekday", session.Timestamp) == 
                            selectedWeekday);
         // get a NotSupportedException here.
         // This function can only be invoked from Linq to Entities
         break;
    case TimeInterval.Weekly:
    case TimeInterval.Monthly:
    case TimeInterval.Annual:
    default:
        // handle these by adjusting the from & through dates?
}

1 个答案:

答案 0 :(得分:3)

我刚刚解决了这个问题。在这里,它适用于任何需要它的人:

        if (!String.IsNullOrWhiteSpace(model.DrillDown))
        {
            switch (model.SelectedInterval)
            {
                case TimeInterval.Weekly:
                    model.FromDate = DateTime.ParseExact(model.DrillDown,"yyyy/MM/dd",CultureInfo.InvariantCulture);
                    model.ThroughDate = model.FromDate.AddDays(6);
                    break;
                case TimeInterval.Monthly:
                    model.FromDate = DateTime.ParseExact(model.DrillDown+"/01", "yyyy/MM/dd", CultureInfo.InvariantCulture);
                    model.ThroughDate = model.FromDate.AddMonths(1).AddDays(-1);
                    break;
                case TimeInterval.Annual:
                    model.FromDate = DateTime.ParseExact(model.DrillDown + "/01/01", "yyyy/MM/dd", CultureInfo.InvariantCulture);
                    model.ThroughDate = model.FromDate.AddYears(1).AddDays(-1);
                    break;
                case TimeInterval.Daily:
                    model.FromDate = DateTime.ParseExact(model.DrillDown, "yyyy/MM/dd", CultureInfo.InvariantCulture);
                    model.ThroughDate = model.FromDate;
                    break;
            }

        }

        var through = model.ThroughDate.AddDays(1);

        var drilldownQuery = DataManager.DataSessions
            .Include("Location")
            .Include("Quote.Carriers")
            .Include("Drivers")
            .Include("Vehicles")
            .Where(session =>
                session.Timestamp >= model.FromDate &&
                session.Timestamp < through
            );

        if (!String.IsNullOrWhiteSpace(model.DrillDown))
        {
            switch (model.SelectedInterval)
            {
                case TimeInterval.Hourly:
                    int selectedHour = int.Parse(model.DrillDown);
                    drilldownQuery = drilldownQuery.Where(session => session.Timestamp.Hour == selectedHour);
                    break;
                case TimeInterval.Weekday:
                    var selectedWeekday = (DayOfWeek) int.Parse(model.DrillDown);
                    drilldownQuery =
                        drilldownQuery.Where(
                            session => session.Timestamp.DayOfWeek == selectedWeekday);
                    break;
            }
        }
        return drilldownQuery;

    }