如何在EFCore Query

时间:2017-04-27 18:11:48

标签: entity-framework entity-framework-core

我正在尝试使用过滤器编写EF查询,并且生成的SQL未在SQL Server上使用WHERE语句。它提取所有数据并在客户端内存上进行过滤。我非常担心性能,并希望在SQL Server上应用过滤器。

要求是计算一小时时段中的记录数。

public async Task<int> GetNumberofSchedules(DateTime dt)
{
    return await _context.Schedules.CountAsync(
        s => s.state == 0
                && s.AppointmentDate.Value.Date == dt.Date
                && s.AppointmentTime.Value.Hours >= dt.Hour
                && s.AppointmentTime.Value.Hours < dt.AddHours(1).Hour
        );
}

示例数据

如果给定DateTime为07/04/2017 08:20,则应返回07/04/2017 08:0007/04/2017 09:00之间的记录数

计数确实返回6这是正确的,但是当我在SQL事件探查器中跟踪生成的SQL时,它会检索所有数据。

enter image description here

在SQL事件探查器中生成SQL

  

选择
  [s]。[EnrolmentRecordID],[s]。[AF1],[s]。[AcademicYearID],[s]。[AdminName],[s]。[AppForm],[s]。[AppointmentDate],   [s]。[AppointmentTime],[s]。[BDT],[s]。[BKSB],[s]。[DateCreated],   [s]。[DateModified],[s]。[雇主],[s]。[EmployerInvited],   [s]。[EmployerReps],[s]。[MIAPP],[s]。[NI],[s]。[ProposedQual],   [s]。[SMT],[s]。[学生邀请],[s]。[学生姓名]

     

这       [dbo]。[EN_Schedules] AS [s]

我想修改我的EF代码以生成WHERE语句并在服务器端执行过滤。我怎样才能实现它?

UPDATE1:

如果我删除了TimeSpan值的过滤器,它会生成正确的SQL语句,如下所示:所以,在我看来,我需要对TimeSpan Field应用不同的过滤器。

  

exec sp_executesql N&#39; SELECT COUNT(*)FROM [dbo]。[EN_Schedules] AS [s]   WHERE([s]。[state] = 0)AND(CONVERT(date,[s]。[AppointmentDate])=   @__ dt_Date_0)&#39;,N&#39; @__ dt_Date_0 datetime2(7)&#39;,@ __ dt_Date_0 =&#39; 2017-04-07   00:00:00&#39;

** Update2:**

通过使用Ivan的解决方案,我最终做到了这样:

var startTime = new TimeSpan(dt.Hour, 0, 0);
var endTime = new TimeSpan(dt.Hour + 1, 0, 0);

return await _context.Schedules.CountAsync(
     s => s.state == 0
          && s.AppointmentDate.Value.Date == dt.Date
          && s.AppointmentTime.Value >= startTime
          && s.AppointmentTime.Value < endTime

 );

2 个答案:

答案 0 :(得分:3)

它确实转换为客户评估 - 看起来EF Core仍然不支持许多TimeSpan操作。

经过大量的反复试验,目前唯一可以将其转换为SQL的方法是将TimeSpan限制作为变量准备并在查询中使用它们:

var startTime = new TimeSpan(dt.Hour, 0, 0);
var endTime = startTime + new TimeSpan(1, 0, 0);

return await _context.Schedules.CountAsync(
    s => s.state == 0
        && s.AppointmentDate.Value.Date == dt.Date
        && s.AppointmentTime.Value >= startTime
        && s.AppointmentTime.Value < endTime
);

答案 1 :(得分:1)

看起来Client Evaluation就是原因。

通过ConfigureWarnings调用禁用它。如果LINQ语句无法转换为SQL,它将给出异常:

public class FooContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder
            .UseSqlServer("foo_connstr")
            .ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning));
    }
}