Skip to content

Commit 5c8c76e

Browse files
committed
Fix type mapping for GETDATE and GETUTCDATE in SqlServer.
1 parent a1e1d46 commit 5c8c76e

File tree

3 files changed

+83
-7
lines changed

3 files changed

+83
-7
lines changed

src/EFCore.SqlServer/Query/Internal/Translators/SqlServerDateTimeMemberTranslator.cs

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,24 @@ public class SqlServerDateTimeMemberTranslator(
6969
returnType),
7070

7171
nameof(DateTime.Now)
72+
when declaringType == typeof(DateTime)
7273
=> sqlExpressionFactory.Function(
73-
declaringType == typeof(DateTime) ? "GETDATE" : "SYSDATETIMEOFFSET",
74+
"GETDATE",
7475
arguments: [],
7576
nullable: false,
7677
argumentsPropagateNullability: [],
77-
returnType),
78+
typeof(DateTime),
79+
typeMappingSource.FindMapping("datetime")),
80+
81+
nameof(DateTimeOffset.Now)
82+
when declaringType == typeof(DateTimeOffset)
83+
=> sqlExpressionFactory.Function(
84+
"SYSDATETIMEOFFSET",
85+
arguments: [],
86+
nullable: false,
87+
argumentsPropagateNullability: [],
88+
typeof(DateTimeOffset),
89+
typeMappingSource.FindMapping("datetimeoffset")),
7890

7991
nameof(DateTime.UtcNow)
8092
when declaringType == typeof(DateTime)
@@ -83,17 +95,21 @@ public class SqlServerDateTimeMemberTranslator(
8395
arguments: [],
8496
nullable: false,
8597
argumentsPropagateNullability: [],
86-
returnType),
98+
typeof(DateTime),
99+
typeMappingSource.FindMapping("datetime")),
87100

88-
nameof(DateTime.UtcNow)
101+
nameof(DateTimeOffset.UtcNow)
89102
when declaringType == typeof(DateTimeOffset)
90103
=> sqlExpressionFactory.Convert(
91104
sqlExpressionFactory.Function(
92105
"SYSUTCDATETIME",
93106
arguments: [],
94107
nullable: false,
95108
argumentsPropagateNullability: [],
96-
returnType), returnType),
109+
typeof(DateTime),
110+
typeMappingSource.FindMapping("datetime2")),
111+
typeof(DateTimeOffset),
112+
typeMappingSource.FindMapping("datetimeoffset")),
97113

98114
nameof(DateTime.Today)
99115
=> sqlExpressionFactory.Function(

test/EFCore.SqlServer.FunctionalTests/Query/Translations/Temporal/DateTimeOffsetTranslationsSqlServerTest.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using Microsoft.EntityFrameworkCore.TestModels.BasicTypesModel;
5+
46
namespace Microsoft.EntityFrameworkCore.Query.Translations.Temporal;
57

68
public class DateTimeOffsetTranslationsSqlServerTest : DateTimeOffsetTranslationsTestBase<BasicTypesQuerySqlServerFixture>
@@ -298,6 +300,34 @@ FROM [BasicTypesEntities] AS [b]
298300
""");
299301
}
300302

303+
[ConditionalFact]
304+
public virtual async Task Now_has_proper_type_mapping_for_constant_comparison()
305+
{
306+
await AssertQuery(
307+
ss => ss.Set<BasicTypesEntity>().Where(x => DateTimeOffset.Now > new DateTimeOffset(2025, 1, 1, 0, 0, 0, TimeSpan.Zero)));
308+
309+
AssertSql(
310+
"""
311+
SELECT [b].[Id], [b].[Bool], [b].[Byte], [b].[ByteArray], [b].[DateOnly], [b].[DateTime], [b].[DateTimeOffset], [b].[Decimal], [b].[Double], [b].[Enum], [b].[FlagsEnum], [b].[Float], [b].[Guid], [b].[Int], [b].[Long], [b].[Short], [b].[String], [b].[TimeOnly], [b].[TimeSpan]
312+
FROM [BasicTypesEntities] AS [b]
313+
WHERE SYSDATETIMEOFFSET() > '2025-01-01T00:00:00.0000000+00:00'
314+
""");
315+
}
316+
317+
[ConditionalFact]
318+
public virtual async Task UtcNow_has_proper_type_mapping_for_constant_comparison()
319+
{
320+
await AssertQuery(
321+
ss => ss.Set<BasicTypesEntity>().Where(x => DateTimeOffset.UtcNow > new DateTimeOffset(2025, 1, 1, 0, 0, 0, TimeSpan.Zero)));
322+
323+
AssertSql(
324+
"""
325+
SELECT [b].[Id], [b].[Bool], [b].[Byte], [b].[ByteArray], [b].[DateOnly], [b].[DateTime], [b].[DateTimeOffset], [b].[Decimal], [b].[Double], [b].[Enum], [b].[FlagsEnum], [b].[Float], [b].[Guid], [b].[Int], [b].[Long], [b].[Short], [b].[String], [b].[TimeOnly], [b].[TimeSpan]
326+
FROM [BasicTypesEntities] AS [b]
327+
WHERE CAST(SYSUTCDATETIME() AS datetimeoffset) > '2025-01-01T00:00:00.0000000+00:00'
328+
""");
329+
}
330+
301331
[ConditionalFact]
302332
public virtual void Check_all_tests_overridden()
303333
=> TestHelpers.AssertAllMethodsOverridden(GetType());

test/EFCore.SqlServer.FunctionalTests/Query/Translations/Temporal/DateTimeTranslationsSqlServerTest.cs

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using Microsoft.EntityFrameworkCore.TestModels.BasicTypesModel;
5+
46
namespace Microsoft.EntityFrameworkCore.Query.Translations.Temporal;
57

68
public class DateTimeTranslationsSqlServerTest : DateTimeTranslationsTestBase<BasicTypesQuerySqlServerFixture>
@@ -18,7 +20,7 @@ public override async Task Now()
1820

1921
AssertSql(
2022
"""
21-
@myDatetime='2015-04-10T00:00:00.0000000'
23+
@myDatetime='2015-04-10T00:00:00.0000000' (DbType = DateTime)
2224
2325
SELECT [b].[Id], [b].[Bool], [b].[Byte], [b].[ByteArray], [b].[DateOnly], [b].[DateTime], [b].[DateTimeOffset], [b].[Decimal], [b].[Double], [b].[Enum], [b].[FlagsEnum], [b].[Float], [b].[Guid], [b].[Int], [b].[Long], [b].[Short], [b].[String], [b].[TimeOnly], [b].[TimeSpan]
2426
FROM [BasicTypesEntities] AS [b]
@@ -32,7 +34,7 @@ public override async Task UtcNow()
3234

3335
AssertSql(
3436
"""
35-
@myDatetime='2015-04-10T00:00:00.0000000'
37+
@myDatetime='2015-04-10T00:00:00.0000000' (DbType = DateTime)
3638
3739
SELECT [b].[Id], [b].[Bool], [b].[Byte], [b].[ByteArray], [b].[DateOnly], [b].[DateTime], [b].[DateTimeOffset], [b].[Decimal], [b].[Double], [b].[Enum], [b].[FlagsEnum], [b].[Float], [b].[Guid], [b].[Int], [b].[Long], [b].[Short], [b].[String], [b].[TimeOnly], [b].[TimeSpan]
3840
FROM [BasicTypesEntities] AS [b]
@@ -241,6 +243,34 @@ FROM [BasicTypesEntities] AS [b]
241243
""");
242244
}
243245

246+
[ConditionalFact]
247+
public virtual async Task Now_has_proper_type_mapping_for_constant_comparison()
248+
{
249+
await AssertQuery(
250+
ss => ss.Set<BasicTypesEntity>().Where(x => DateTime.Now > new DateTime(2025, 1, 1)));
251+
252+
AssertSql(
253+
"""
254+
SELECT [b].[Id], [b].[Bool], [b].[Byte], [b].[ByteArray], [b].[DateOnly], [b].[DateTime], [b].[DateTimeOffset], [b].[Decimal], [b].[Double], [b].[Enum], [b].[FlagsEnum], [b].[Float], [b].[Guid], [b].[Int], [b].[Long], [b].[Short], [b].[String], [b].[TimeOnly], [b].[TimeSpan]
255+
FROM [BasicTypesEntities] AS [b]
256+
WHERE GETDATE() > '2025-01-01T00:00:00.000'
257+
""");
258+
}
259+
260+
[ConditionalFact]
261+
public virtual async Task UtcNow_has_proper_type_mapping_for_constant_comparison()
262+
{
263+
await AssertQuery(
264+
ss => ss.Set<BasicTypesEntity>().Where(x => DateTime.UtcNow > new DateTime(2025, 1, 1)));
265+
266+
AssertSql(
267+
"""
268+
SELECT [b].[Id], [b].[Bool], [b].[Byte], [b].[ByteArray], [b].[DateOnly], [b].[DateTime], [b].[DateTimeOffset], [b].[Decimal], [b].[Double], [b].[Enum], [b].[FlagsEnum], [b].[Float], [b].[Guid], [b].[Int], [b].[Long], [b].[Short], [b].[String], [b].[TimeOnly], [b].[TimeSpan]
269+
FROM [BasicTypesEntities] AS [b]
270+
WHERE GETUTCDATE() > '2025-01-01T00:00:00.000'
271+
""");
272+
}
273+
244274
[ConditionalFact]
245275
public virtual void Check_all_tests_overridden()
246276
=> TestHelpers.AssertAllMethodsOverridden(GetType());

0 commit comments

Comments
 (0)