优化实体框架

时间:2017-10-25 22:17:33

标签: c# entity-framework linq optimization entity-framework-6

我正在尝试优化我们最重要的查询之一,并希望对实体框架如何翻译某些LINQ表达式有一些额外的见解。

我正在使用存储库模式,所以我的服务层(我定义我的查询)不知道实际的数据层,它(目前)限制我只使用Where语句。使用连接和其他构造可能会有所帮助,但这需要重写应用程序的某些部分。在考虑之前,我想先耗尽所有其他选项。

我提出了3个查询变体:

// Takes about 1900-2200ms for 120 records 
public Expression<Func<Appointment, bool>> FilterByResources(DateTime startDate, DateTime endDate, IEnumerable<int> resourceIds)
    {
        // Appointments are filtered on the scheduler's start date, end date and the resources in the current page            
        Expression<Func<Appointment, bool>> filter = (x) => x.Assignments.Any(z => resourceIds.Contains(z.ResourceId))
        &&
        // Appointment starts somewhere between the start and end date
        ((DbFunctions.TruncateTime(x.StartDate).Value >= startDate && DbFunctions.TruncateTime(x.StartDate).Value <= endDate) ||

         // Appointment started earlier than start date but ends earlier than end date
         (DbFunctions.TruncateTime(x.EndDate).Value >= startDate && DbFunctions.TruncateTime(x.EndDate).Value <= endDate) ||

         // Appointment starts and ends outside the boundaries
         (DbFunctions.TruncateTime(x.StartDate).Value <= startDate && DbFunctions.TruncateTime(x.EndDate).Value >= endDate));

        return filter;
}

备选方案#2:

// Takes about 2100ms for 120 records
public Expression<Func<Appointment, bool>> FilterByResources2(DateTime startDate, DateTime endDate, IEnumerable<int> resourceIds)
{
        DateTime truncatedStartDate = startDate.Date;
        DateTime truncatedEndDate = endDate.EndOfDay(); // Extension method that formats the time to 23:59:59

        // Appointments are filtered on the scheduler's start date, end date and the resources in the current page            
        Expression<Func<Appointment, bool>> filter = (x) => x.Assignments.Any(z => resourceIds.Contains(z.ResourceId)) && (
         (x.StartDate >= truncatedStartDate && x.StartDate <= truncatedEndDate) || // Appointment starts somewhere between the start and end date             
         (x.EndDate >= truncatedStartDate && x.EndDate <= truncatedEndDate) || // Appointment started earlier than start date but ends earlier than end date             
         (x.StartDate <= truncatedStartDate && x.EndDate >= truncatedEndDate) // Appointment starts and ends outside the boundaries
        );

        return filter;
}

备选方案3:

// Takes about 1900ms for 120 records
public Expression<Func<Appointment, bool>> FilterByResources(DateTime startDate, DateTime endDate, IEnumerable<int> resourceIds)
{
        DateTime truncatedStartDate = startDate.Date;
        DateTime truncatedEndDate = endDate.EndOfDay(); // Extension method that formats the time to 23:59:59

        // Appointments are filtered on the scheduler's start date, end date and the resources in the current page            
        Expression<Func<Appointment, bool>> filter = (x) => x.Assignments.Any(z => resourceIds.Contains(z.ResourceId)) && (
         (x.StartDate.CompareTo(truncatedStartDate) >= 0 && x.StartDate.CompareTo(truncatedEndDate) <= 0) || // Appointment starts somewhere between the start and end date             
         (x.EndDate.CompareTo(truncatedStartDate) >= 0 && x.EndDate.CompareTo(truncatedEndDate) <= 0) || // Appointment started earlier than start date but ends earlier than end date             
         (x.StartDate.CompareTo(truncatedStartDate) <= 0 && x.EndDate.CompareTo(truncatedEndDate) >= 0) // Appointment starts and ends outside the boundaries
        );

        return filter;
}

关于此查询的一点解释:此查询检索两个日期之间的多个资源(即人员)的约会列表。由于该范围,我需要包括那些先前开始,后期完成或持续时间超过范围的记录(因此是3个表达式)。

我尝试切换表达式的顺序,但结果保持稳定。对于整个网络API呼叫,平均需要1800毫秒到2200毫秒(我使用邮递员进行测试)

所以我的问题是如何优化这个查询?我认为日期比较表达式花费的时间最长,但也可能是Any / Contains组合会降低查询速度。

0 个答案:

没有答案