Как получить сгенерированный EntityFrameworkCore SQL, чтобы использовать правильный формат для объектов DateTime? - PullRequest
0 голосов
/ 28 августа 2018

Я использую Microsoft.EntityFrameworkCore.SqlServer v2.1.2 (а также пробовал v2.2.0-preview1-35029) и использую LINQ для получения коллекции сущностей из базы данных Azure SqlServer, фильтрация по полю DateTime.

Однако SQL, сгенерированный оператором LINQ, использует строковое значение DateTime, которое SqlServer отклоняет с этой ошибкой:

Ошибка преобразования при преобразовании даты и / или времени из символьной строки.

Я могу изменить инструкцию SQL, чтобы изменить формат даты и времени, чтобы запрос работал без ошибок (подробности см. Ниже), но я не знаю, как заставить среду генерировать этот же формат даты и времени.

Хотя EntityFrameworkCore все еще нова, похоже, что это довольно простой вариант использования, поэтому я предполагаю, что я делаю что-то не так, и это не проблема фреймворка.

Как запретить EF генерировать недопустимое значение даты и времени в SQL?

и / или

Как заставить сгенерированный SQL использовать другой формат для объектов DateTime?


Модель EntityFramework, которую я использую, выглядит следующим образом:

public class DeskReading
{
    public int DeskReadingId { get; set; }
    //... some other fields ...
    public DateTime Timestamp { get; set; }
}

И мой LINQ для запроса значений выглядит так:

IQueryable<DeskReading> readings = 
    _dbContext.DeskReadings
            .OrderBy(gr => gr.Timestamp)
            .Where(gr => gr.Timestamp > new DateTime(2017, 05, 01));

readings.ToList();

И генерируемый SQL-код выглядит следующим образом:

SELECT [gr].[DeskReadingId] --...some other fields ...
FROM [DeskReadings] AS [gr]
WHERE [gr].[Timestamp] > '2017-05-01T00:00:00.0000000'
ORDER BY [gr].[Timestamp]

Обратите внимание, что значение фильтра '2017-05-01T00:00:00.0000000'

Если я запускаю этот SQL напрямую на SqlServer через SSMS, я получаю ту же ошибку:

enter image description here

Но если я поменяю фильтр на '2017-05-01 00:00:00', он будет работать нормально:

SELECT [gr].[DeskReadingId] --...some other fields ...
FROM [DeskReadings] AS [gr]
WHERE [gr].[Timestamp] > '2017-05-01 00:00:00'
ORDER BY [gr].[Timestamp]

В соответствии с просьбой, вот скрипт создания для таблицы:

CREATE TABLE [dbo].[DeskReadings](
    [DeskReadingId] [int] IDENTITY(1,1) NOT NULL,
    [SoilMoistureSensor1] [int] NOT NULL,
    [SoilMoistureSensor2] [int] NOT NULL,
    [LightLevel] [int] NOT NULL,
    [TemperatureF] [real] NOT NULL,
    [HumidityPercent] [real] NOT NULL,
    [Timestamp] [datetime] NOT NULL,
 CONSTRAINT [PK_dbo.DeskReadings] PRIMARY KEY CLUSTERED 
(
    [DeskReadingId] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

1 Ответ

0 голосов
/ 28 августа 2018

При просмотре исходного кода на GitHub , существует условное форматирование, которое EntityFrameworkCore использует на основе StoreType, которому он считает столбец в выражении. Например, формат, который вы видите, явно для datetime2. Ошибка, возникающая при сравнении столбца datetime со строкой в ​​формате datetime2.

Вот источник, на который я ссылаюсь, есть три строковых константы, которые представляют формат для значения C # DateTime:

    private const string DateFormatConst = "{0:yyyy-MM-dd}";
    private const string DateTimeFormatConst = "{0:yyyy-MM-ddTHH:mm:ss.fffK}";
    private const string DateTime2FormatConst = "{0:yyyy-MM-ddTHH:mm:ss.fffffffK}";

Форматы https://github.com/aspnet/EntityFrameworkCore/blob/release/2.2/src/EFCore.SqlServer/Storage/Internal/SqlServerDateTimeTypeMapping.cs#L18-L20

Условная логика https://github.com/aspnet/EntityFrameworkCore/blob/release/2.2/src/EFCore.SqlServer/Storage/Internal/SqlServerDateTimeTypeMapping.cs#L70-L74

Чтобы устранить эту проблему, вы можете приписать свою модель так:

public class DeskReading
{
    public int DeskReadingId { get; set; }

    [Column(TypeName="datetime")]
    public DateTime Timestamp { get; set; }
}

Это заставит сравнения рассматривать его как StoreType из datetime и правильно его форматировать.

...