我正在使用Microsoft.EntityFrameworkCore.SqlServer v2.1.2(并且还尝试过v2.2.0-preview1-35029),并且正在使用LINQ从Azure SqlServer数据库中获取实体集合,并在DateTime字段上进行过滤。
但是,LINQ语句生成的SQL使用基于字符串的DateTime值,SqlServer会由于以下错误而拒绝该值:
从字符串转换日期和/或时间时转换失败。
我可以修改SQL语句以更改日期时间格式,以使查询正常运行(请参见下文以了解详细信息),但是我不知道如何获取框架以生成相同的日期时间格式。
虽然EntityFrameworkCore仍然是一个新事物,但看来这是一个非常简单的用例,因此我假设我做错了什么,这不是框架问题。
如何防止EF在SQL中生成无效的datetime值?
和/或
如何获取生成的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'
如果我通过SSMS直接在SqlServer上运行该SQL,则会收到相同的错误:
但是,如果我将过滤器更改为使用'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]
答案 0 :(得分:2)
在 GitHub 上查看源代码时, EntityFrameworkCore 使用一种条件格式,该格式基于它认为表达式中的列为StoreType的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}";
要解决此特定问题,您可以将模型归为这样:
public class DeskReading
{
public int DeskReadingId { get; set; }
[Column(TypeName="datetime")]
public DateTime Timestamp { get; set; }
}
这将迫使比较将其视为StoreType
的{{1}},并正确设置其格式。