From f3b86957dbabf4f119eacee0f0a31e41eb6036e2 Mon Sep 17 00:00:00 2001 From: Roma Marusyk Date: Wed, 25 Dec 2019 03:46:11 +0200 Subject: [PATCH 01/11] Add DATEFROMPARTS function to SqlServer --- .../SqlServerDbFunctionsExtensions.cs | 16 +++++++ ...qlServerDateFromPartsFunctionTranslator.cs | 42 +++++++++++++++++++ .../SqlServerMethodCallTranslatorProvider.cs | 2 +- .../NorthwindDbFunctionsQuerySqlServerTest.cs | 17 ++++++++ 4 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 src/EFCore.SqlServer/Query/Internal/SqlServerDateFromPartsFunctionTranslator.cs diff --git a/src/EFCore.SqlServer/Extensions/SqlServerDbFunctionsExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerDbFunctionsExtensions.cs index 6c2995a9e7b..947d2c413cd 100644 --- a/src/EFCore.SqlServer/Extensions/SqlServerDbFunctionsExtensions.cs +++ b/src/EFCore.SqlServer/Extensions/SqlServerDbFunctionsExtensions.cs @@ -1007,5 +1007,21 @@ public static DateTime DateTimeFromParts( int second, int millisecond) => throw new InvalidOperationException(SqlServerStrings.FunctionOnClient(nameof(DateTimeFromParts))); + + /// + /// Initializes a new instance of the structure to the specified year, month, day. + /// Corresponds to the SQL Server's DATEFROMPARTS(year, month, day). + /// + /// The DbFunctions instance. + /// The year (1753 through 9999). + /// The month (1 through 12). + /// The day (1 through the number of days in month). + /// New instance of the structure to the specified year, month, day. + public static DateTime DateFromParts( + [CanBeNull] this DbFunctions _, + int year, + int month, + int day) + => throw new InvalidOperationException(SqlServerStrings.FunctionOnClient(nameof(DateFromParts))); } } diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerDateFromPartsFunctionTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerDateFromPartsFunctionTranslator.cs new file mode 100644 index 00000000000..a21d3eb3aae --- /dev/null +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerDateFromPartsFunctionTranslator.cs @@ -0,0 +1,42 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Storage; + +namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal +{ + public class SqlServerDateFromPartsFunctionTranslator : IMethodCallTranslator + { + private readonly ISqlExpressionFactory _sqlExpressionFactory; + private readonly IRelationalTypeMappingSource _typeMappingSource; + + private static readonly MethodInfo _methodInfo = typeof(SqlServerDbFunctionsExtensions) + .GetRuntimeMethod(nameof(SqlServerDbFunctionsExtensions.DateFromParts), new[] { typeof(DbFunctions), typeof(int), typeof(int), typeof(int) }); + + public SqlServerDateFromPartsFunctionTranslator( + [NotNull] ISqlExpressionFactory sqlExpressionFactory, + [NotNull] IRelationalTypeMappingSource typeMappingSource) + { + _sqlExpressionFactory = sqlExpressionFactory; + _typeMappingSource = typeMappingSource; + } + + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) + { + return _methodInfo.Equals(method) + ? _sqlExpressionFactory.Function( + "DATEFROMPARTS", + arguments.Skip(1), + _methodInfo.ReturnType, + _typeMappingSource.FindMapping(typeof(DateTime), "datetime")) + : null; + } + } +} diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerMethodCallTranslatorProvider.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerMethodCallTranslatorProvider.cs index 3e47cfcb6ca..fb8ff94eb51 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerMethodCallTranslatorProvider.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerMethodCallTranslatorProvider.cs @@ -3,7 +3,6 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.Storage; namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { @@ -21,6 +20,7 @@ public SqlServerMethodCallTranslatorProvider([NotNull] RelationalMethodCallTrans new SqlServerConvertTranslator(sqlExpressionFactory), new SqlServerDateDiffFunctionsTranslator(sqlExpressionFactory), new SqlServerDateTimeFromPartsFunctionTranslator(sqlExpressionFactory, typeMappingSource), + new SqlServerDateFromPartsFunctionTranslator(sqlExpressionFactory, typeMappingSource), new SqlServerDateTimeMethodTranslator(sqlExpressionFactory), new SqlServerFullTextSearchFunctionsTranslator(sqlExpressionFactory), new SqlServerIsDateFunctionTranslator(sqlExpressionFactory), diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindDbFunctionsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindDbFunctionsQuerySqlServerTest.cs index fba3bd9c20e..0f4a349cd5d 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindDbFunctionsQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindDbFunctionsQuerySqlServerTest.cs @@ -697,6 +697,23 @@ FROM [Orders] AS [o] } } + [ConditionalFact] + public virtual void DateFromParts_column_compare() + { + using (var context = CreateContext()) + { + var count = context.Orders + .Count(c => c.OrderDate > EF.Functions.DateFromParts(DateTime.Now.Year, 12, 31)); + + Assert.Equal(0, count); + + AssertSql( + @"SELECT COUNT(*) +FROM [Orders] AS [o] +WHERE [o].[OrderDate] > DATEFROMPARTS(DATEPART(year, GETDATE()), 12, 31)"); + } + } + [ConditionalFact] public virtual void DateTimeFromParts_constant_compare() { From fb0019fde804193f91f53b6b050414ba444ad0da Mon Sep 17 00:00:00 2001 From: Roma Marusyk Date: Wed, 25 Dec 2019 15:49:29 +0200 Subject: [PATCH 02/11] Add tests --- .../NorthwindDbFunctionsQuerySqlServerTest.cs | 63 +++++++++++++++---- 1 file changed, 51 insertions(+), 12 deletions(-) diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindDbFunctionsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindDbFunctionsQuerySqlServerTest.cs index 0f4a349cd5d..e401ad751d7 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindDbFunctionsQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindDbFunctionsQuerySqlServerTest.cs @@ -697,6 +697,49 @@ FROM [Orders] AS [o] } } + [ConditionalFact] + public virtual void DateTimeFromParts_constant_compare() + { + using (var context = CreateContext()) + { + var count = context.Orders + .Count(c => new DateTime(2018, 12, 29, 23, 20, 40) > EF.Functions.DateTimeFromParts(DateTime.Now.Year, 12, 31, 23, 59, 59, 999)); + + Assert.Equal(0, count); + + AssertSql( + @"SELECT COUNT(*) +FROM [Orders] AS [o] +WHERE '2018-12-29T23:20:40.000' > DATETIMEFROMPARTS(DATEPART(year, GETDATE()), 12, 31, 23, 59, 59, 999)"); + } + } + + [ConditionalFact] + public virtual void DateTimeFromParts_compare_with_local_variable() + { + var dateTime = new DateTime(1919, 12, 12, 10, 20, 15, 0); + using (var context = CreateContext()) + { + var count = context.Orders + .Count(c => dateTime > EF.Functions.DateTimeFromParts(DateTime.Now.Year, dateTime.Month, dateTime.Day, dateTime.Hour, dateTime.Minute, dateTime.Second, dateTime.Millisecond)); + + Assert.Equal(0, count); + + AssertSql( + @$"@__dateTime_0='1919-12-12T10:20:15' (DbType = DateTime) +@__dateTime_Month_2='12' +@__dateTime_Day_3='12' +@__dateTime_Hour_4='10' +@__dateTime_Minute_5='20' +@__dateTime_Second_6='15' +@__dateTime_Millisecond_7='0' + +SELECT COUNT(*) +FROM [Orders] AS [o] +WHERE @__dateTime_0 > DATETIMEFROMPARTS(DATEPART(year, GETDATE()), @__dateTime_Month_2, @__dateTime_Day_3, @__dateTime_Hour_4, @__dateTime_Minute_5, @__dateTime_Second_6, @__dateTime_Millisecond_7)"); + } + } + [ConditionalFact] public virtual void DateFromParts_column_compare() { @@ -715,45 +758,41 @@ FROM [Orders] AS [o] } [ConditionalFact] - public virtual void DateTimeFromParts_constant_compare() + public virtual void DateFromParts_constant_compare() { using (var context = CreateContext()) { var count = context.Orders - .Count(c => new DateTime(2018, 12, 29, 23, 20, 40) > EF.Functions.DateTimeFromParts(DateTime.Now.Year, 12, 31, 23, 59, 59, 999)); + .Count(c => new DateTime(2018, 12, 29) > EF.Functions.DateFromParts(DateTime.Now.Year, 12, 31)); Assert.Equal(0, count); AssertSql( @"SELECT COUNT(*) FROM [Orders] AS [o] -WHERE '2018-12-29T23:20:40.000' > DATETIMEFROMPARTS(DATEPART(year, GETDATE()), 12, 31, 23, 59, 59, 999)"); +WHERE '2018-12-29T00:00:00.000' > DATEFROMPARTS(DATEPART(year, GETDATE()), 12, 31)"); } } [ConditionalFact] - public virtual void DateTimeFromParts_compare_with_local_variable() + public virtual void DateFromParts_compare_with_local_variable() { - var dateTime = new DateTime(1919, 12, 12, 10, 20, 15, 0); + var dateTime = new DateTime(1919, 12, 12); using (var context = CreateContext()) { var count = context.Orders - .Count(c => dateTime > EF.Functions.DateTimeFromParts(DateTime.Now.Year, dateTime.Month, dateTime.Day, dateTime.Hour, dateTime.Minute, dateTime.Second, dateTime.Millisecond)); + .Count(c => dateTime > EF.Functions.DateFromParts(DateTime.Now.Year, dateTime.Month, dateTime.Day)); Assert.Equal(0, count); AssertSql( - @$"@__dateTime_0='1919-12-12T10:20:15' (DbType = DateTime) + @$"@__dateTime_0='1919-12-12T00:00:00' (DbType = DateTime) @__dateTime_Month_2='12' @__dateTime_Day_3='12' -@__dateTime_Hour_4='10' -@__dateTime_Minute_5='20' -@__dateTime_Second_6='15' -@__dateTime_Millisecond_7='0' SELECT COUNT(*) FROM [Orders] AS [o] -WHERE @__dateTime_0 > DATETIMEFROMPARTS(DATEPART(year, GETDATE()), @__dateTime_Month_2, @__dateTime_Day_3, @__dateTime_Hour_4, @__dateTime_Minute_5, @__dateTime_Second_6, @__dateTime_Millisecond_7)"); +WHERE @__dateTime_0 > DATEFROMPARTS(DATEPART(year, GETDATE()), @__dateTime_Month_2, @__dateTime_Day_3)"); } } From 98c4c55c2acf0be4dcde4f01d8a187dca53ba88f Mon Sep 17 00:00:00 2001 From: Roma Marusyk Date: Wed, 25 Dec 2019 18:44:04 +0200 Subject: [PATCH 03/11] Add DATETIME2FROMPARTS function --- .../SqlServerDbFunctionsExtensions.cs | 27 ++++++++++++ ...verDateTime2FromPartsFunctionTranslator.cs | 44 +++++++++++++++++++ .../SqlServerMethodCallTranslatorProvider.cs | 1 + 3 files changed, 72 insertions(+) create mode 100644 src/EFCore.SqlServer/Query/Internal/SqlServerDateTime2FromPartsFunctionTranslator.cs diff --git a/src/EFCore.SqlServer/Extensions/SqlServerDbFunctionsExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerDbFunctionsExtensions.cs index 947d2c413cd..e6d440e179e 100644 --- a/src/EFCore.SqlServer/Extensions/SqlServerDbFunctionsExtensions.cs +++ b/src/EFCore.SqlServer/Extensions/SqlServerDbFunctionsExtensions.cs @@ -1023,5 +1023,32 @@ public static DateTime DateFromParts( int month, int day) => throw new InvalidOperationException(SqlServerStrings.FunctionOnClient(nameof(DateFromParts))); + + /// + /// Initializes a new instance of the structure to the specified year, month, day, hour, minute, second, fractions, and precision. + /// Corresponds to the SQL Server's DATETIME2FROMPARTS (year, month, day, hour, minute, seconds, fractions, precision). + /// + /// The DbFunctions instance. + /// The year (1753 through 9999). + /// The month (1 through 12). + /// The day (1 through the number of days in month). + /// The hours (0 through 23). + /// The minutes (0 through 59). + /// The seconds (0 through 59). + /// The fractional seconds. + /// The precision of the datetime2 value. + /// New instance of the structure to the specified year, month, day, hour, minute, second, fractions, and precision. + public static DateTime DateTime2FromParts( + [CanBeNull] this DbFunctions _, + int year, + int month, + int day, + int hour, + int minute, + int second, + int fractions, + int precision + ) + => throw new InvalidOperationException(SqlServerStrings.FunctionOnClient(nameof(DateTime2FromParts))); } } diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerDateTime2FromPartsFunctionTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerDateTime2FromPartsFunctionTranslator.cs new file mode 100644 index 00000000000..aa8b5491855 --- /dev/null +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerDateTime2FromPartsFunctionTranslator.cs @@ -0,0 +1,44 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Storage; + +namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal +{ + public class SqlServerDateTime2FromPartsFunctionTranslator : IMethodCallTranslator + { + private readonly ISqlExpressionFactory _sqlExpressionFactory; + private readonly IRelationalTypeMappingSource _typeMappingSource; + + private static readonly MethodInfo _methodInfo = typeof(SqlServerDbFunctionsExtensions) + .GetRuntimeMethod(nameof(SqlServerDbFunctionsExtensions.DateTime2FromParts), new[] { typeof(DbFunctions), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int) }); + + public SqlServerDateTime2FromPartsFunctionTranslator( + [NotNull] ISqlExpressionFactory sqlExpressionFactory, + [NotNull] IRelationalTypeMappingSource typeMappingSource) + { + _sqlExpressionFactory = sqlExpressionFactory; + _typeMappingSource = typeMappingSource; + } + + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) + { + return _methodInfo.Equals(method) + ? _sqlExpressionFactory.Function( + "DATETIME2FROMPARTS", + arguments.Skip(1), + _methodInfo.ReturnType, + _typeMappingSource.FindMapping(typeof(DateTime), "datetime")) + : null; + } + } +} + +// diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerMethodCallTranslatorProvider.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerMethodCallTranslatorProvider.cs index fb8ff94eb51..d476ca5af9b 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerMethodCallTranslatorProvider.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerMethodCallTranslatorProvider.cs @@ -21,6 +21,7 @@ public SqlServerMethodCallTranslatorProvider([NotNull] RelationalMethodCallTrans new SqlServerDateDiffFunctionsTranslator(sqlExpressionFactory), new SqlServerDateTimeFromPartsFunctionTranslator(sqlExpressionFactory, typeMappingSource), new SqlServerDateFromPartsFunctionTranslator(sqlExpressionFactory, typeMappingSource), + new SqlServerDateTime2FromPartsFunctionTranslator(sqlExpressionFactory, typeMappingSource), new SqlServerDateTimeMethodTranslator(sqlExpressionFactory), new SqlServerFullTextSearchFunctionsTranslator(sqlExpressionFactory), new SqlServerIsDateFunctionTranslator(sqlExpressionFactory), From 0355821954a86212e410f2f97c2c29ea5b0d8655 Mon Sep 17 00:00:00 2001 From: Roma Marusyk Date: Wed, 25 Dec 2019 19:27:21 +0200 Subject: [PATCH 04/11] Add DATETIMEOFFSETFROMPARTS, SMALLDATETIMEFROMPARTS, TIMEFROMPARTS functions --- .../SqlServerDbFunctionsExtensions.cs | 73 ++++++++++++++++++- ...teTimeOffsetFromPartsFunctionTranslator.cs | 44 +++++++++++ .../SqlServerMethodCallTranslatorProvider.cs | 7 +- ...mallDateTimeFromPartsFunctionTranslator.cs | 44 +++++++++++ ...qlServerTimeFromPartsFunctionTranslator.cs | 44 +++++++++++ 5 files changed, 208 insertions(+), 4 deletions(-) create mode 100644 src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeOffsetFromPartsFunctionTranslator.cs create mode 100644 src/EFCore.SqlServer/Query/Internal/SqlServerSmallDateTimeFromPartsFunctionTranslator.cs create mode 100644 src/EFCore.SqlServer/Query/Internal/SqlServerTimeFromPartsFunctionTranslator.cs diff --git a/src/EFCore.SqlServer/Extensions/SqlServerDbFunctionsExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerDbFunctionsExtensions.cs index e6d440e179e..18aa22e0c80 100644 --- a/src/EFCore.SqlServer/Extensions/SqlServerDbFunctionsExtensions.cs +++ b/src/EFCore.SqlServer/Extensions/SqlServerDbFunctionsExtensions.cs @@ -1047,8 +1047,77 @@ public static DateTime DateTime2FromParts( int minute, int second, int fractions, - int precision - ) + int precision) => throw new InvalidOperationException(SqlServerStrings.FunctionOnClient(nameof(DateTime2FromParts))); + + /// + /// Initializes a new instance of the structure to the specified year, month, day, hour, minute, second, fractions, hourOffset, minuteOffset and precision. + /// Corresponds to the SQL Server's DATETIMEOFFSETFROMPARTS (year, month, day, hour, minute, seconds, fractions, hour_offset, minute_offset, precision). + /// + /// The DbFunctions instance. + /// The year (1753 through 9999). + /// The month (1 through 12). + /// The day (1 through the number of days in month). + /// The hours (0 through 23). + /// The minutes (0 through 59). + /// The seconds (0 through 59). + /// The fractional seconds. + /// The hour portion of the time zone offset. + /// The minute portion of the time zone offset. + /// The precision of the datetime2 value. + /// New instance of the structure to the specified year, month, day, hour, minute, second, fractions, hourOffset, minuteOffset and precision. + public static DateTime DateTimeOffsetFromParts( + [CanBeNull] this DbFunctions _, + int year, + int month, + int day, + int hour, + int minute, + int second, + int fractions, + int hourOffset, + int minuteOffset, + int precision) + => throw new InvalidOperationException(SqlServerStrings.FunctionOnClient(nameof(DateTimeOffsetFromParts))); + + /// + /// Initializes a new instance of the structure to the specified year, month, day, hour and minute. + /// Corresponds to the SQL Server's SMALLDATETIMEFROMPARTS (year, month, day, hour, minute). + /// + /// The DbFunctions instance. + /// The year (1753 through 9999). + /// The month (1 through 12). + /// The day (1 through the number of days in month). + /// The hours (0 through 23). + /// The minutes (0 through 59). + /// New instance of the structure to the specified year, month, day, hour and minute. + public static DateTime SmallDateTimeFromParts( + [CanBeNull] this DbFunctions _, + int year, + int month, + int day, + int hour, + int minute) + => throw new InvalidOperationException(SqlServerStrings.FunctionOnClient(nameof(SmallDateTimeFromParts))); + + /// + /// Initializes a new instance of the structure to the specified hour, minute, second, fractions, and precision. + /// Corresponds to the SQL Server's TIMEFROMPARTS (hour, minute, seconds, fractions, precision). + /// + /// The DbFunctions instance. + /// The hours (0 through 23). + /// The minutes (0 through 59). + /// The seconds (0 through 59). + /// The fractional seconds. + /// The precision of the time value. + /// New instance of the structure to the specified hour, minute, second, fractions, and precision. + public static DateTime TimeFromParts( + [CanBeNull] this DbFunctions _, + int hour, + int minute, + int second, + int fractions, + int precision) + => throw new InvalidOperationException(SqlServerStrings.FunctionOnClient(nameof(TimeFromParts))); } } diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeOffsetFromPartsFunctionTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeOffsetFromPartsFunctionTranslator.cs new file mode 100644 index 00000000000..9d863c3c148 --- /dev/null +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeOffsetFromPartsFunctionTranslator.cs @@ -0,0 +1,44 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Storage; + +namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal +{ + public class SqlServerDateTimeOffsetFromPartsFunctionTranslator : IMethodCallTranslator + { + private readonly ISqlExpressionFactory _sqlExpressionFactory; + private readonly IRelationalTypeMappingSource _typeMappingSource; + + private static readonly MethodInfo _methodInfo = typeof(SqlServerDbFunctionsExtensions) + .GetRuntimeMethod(nameof(SqlServerDbFunctionsExtensions.DateTimeOffsetFromParts), new[] { typeof(DbFunctions), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int) }); + + public SqlServerDateTimeOffsetFromPartsFunctionTranslator( + [NotNull] ISqlExpressionFactory sqlExpressionFactory, + [NotNull] IRelationalTypeMappingSource typeMappingSource) + { + _sqlExpressionFactory = sqlExpressionFactory; + _typeMappingSource = typeMappingSource; + } + + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) + { + return _methodInfo.Equals(method) + ? _sqlExpressionFactory.Function( + "DATETIMEOFFSETFROMPARTS", + arguments.Skip(1), + _methodInfo.ReturnType, + _typeMappingSource.FindMapping(typeof(DateTime), "datetime")) + : null; + } + } +} + +// diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerMethodCallTranslatorProvider.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerMethodCallTranslatorProvider.cs index d476ca5af9b..447251a937c 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerMethodCallTranslatorProvider.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerMethodCallTranslatorProvider.cs @@ -19,16 +19,19 @@ public SqlServerMethodCallTranslatorProvider([NotNull] RelationalMethodCallTrans new SqlServerByteArrayMethodTranslator(sqlExpressionFactory), new SqlServerConvertTranslator(sqlExpressionFactory), new SqlServerDateDiffFunctionsTranslator(sqlExpressionFactory), - new SqlServerDateTimeFromPartsFunctionTranslator(sqlExpressionFactory, typeMappingSource), new SqlServerDateFromPartsFunctionTranslator(sqlExpressionFactory, typeMappingSource), new SqlServerDateTime2FromPartsFunctionTranslator(sqlExpressionFactory, typeMappingSource), + new SqlServerDateTimeFromPartsFunctionTranslator(sqlExpressionFactory, typeMappingSource), new SqlServerDateTimeMethodTranslator(sqlExpressionFactory), + new SqlServerDateTimeOffsetFromPartsFunctionTranslator(sqlExpressionFactory, typeMappingSource), new SqlServerFullTextSearchFunctionsTranslator(sqlExpressionFactory), new SqlServerIsDateFunctionTranslator(sqlExpressionFactory), new SqlServerMathTranslator(sqlExpressionFactory), new SqlServerNewGuidTranslator(sqlExpressionFactory), new SqlServerObjectToStringTranslator(sqlExpressionFactory), - new SqlServerStringMethodTranslator(sqlExpressionFactory) + new SqlServerSmallDateTimeFromPartsFunctionTranslator(sqlExpressionFactory, typeMappingSource), + new SqlServerStringMethodTranslator(sqlExpressionFactory), + new SqlServerTimeFromPartsFunctionTranslator(sqlExpressionFactory, typeMappingSource) }); } } diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerSmallDateTimeFromPartsFunctionTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerSmallDateTimeFromPartsFunctionTranslator.cs new file mode 100644 index 00000000000..00c33468fe9 --- /dev/null +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerSmallDateTimeFromPartsFunctionTranslator.cs @@ -0,0 +1,44 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Storage; + +namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal +{ + public class SqlServerSmallDateTimeFromPartsFunctionTranslator : IMethodCallTranslator + { + private readonly ISqlExpressionFactory _sqlExpressionFactory; + private readonly IRelationalTypeMappingSource _typeMappingSource; + + private static readonly MethodInfo _methodInfo = typeof(SqlServerDbFunctionsExtensions) + .GetRuntimeMethod(nameof(SqlServerDbFunctionsExtensions.SmallDateTimeFromParts), new[] { typeof(DbFunctions), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int) }); + + public SqlServerSmallDateTimeFromPartsFunctionTranslator( + [NotNull] ISqlExpressionFactory sqlExpressionFactory, + [NotNull] IRelationalTypeMappingSource typeMappingSource) + { + _sqlExpressionFactory = sqlExpressionFactory; + _typeMappingSource = typeMappingSource; + } + + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) + { + return _methodInfo.Equals(method) + ? _sqlExpressionFactory.Function( + "SMALLDATETIMEFROMPARTS", + arguments.Skip(1), + _methodInfo.ReturnType, + _typeMappingSource.FindMapping(typeof(DateTime), "datetime")) + : null; + } + } +} + +// diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerTimeFromPartsFunctionTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerTimeFromPartsFunctionTranslator.cs new file mode 100644 index 00000000000..a31fcb34ce0 --- /dev/null +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerTimeFromPartsFunctionTranslator.cs @@ -0,0 +1,44 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Storage; + +namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal +{ + public class SqlServerTimeFromPartsFunctionTranslator : IMethodCallTranslator + { + private readonly ISqlExpressionFactory _sqlExpressionFactory; + private readonly IRelationalTypeMappingSource _typeMappingSource; + + private static readonly MethodInfo _methodInfo = typeof(SqlServerDbFunctionsExtensions) + .GetRuntimeMethod(nameof(SqlServerDbFunctionsExtensions.TimeFromParts), new[] { typeof(DbFunctions), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int) }); + + public SqlServerTimeFromPartsFunctionTranslator( + [NotNull] ISqlExpressionFactory sqlExpressionFactory, + [NotNull] IRelationalTypeMappingSource typeMappingSource) + { + _sqlExpressionFactory = sqlExpressionFactory; + _typeMappingSource = typeMappingSource; + } + + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) + { + return _methodInfo.Equals(method) + ? _sqlExpressionFactory.Function( + "TIMEFROMPARTS", + arguments.Skip(1), + _methodInfo.ReturnType, + _typeMappingSource.FindMapping(typeof(DateTime), "datetime")) + : null; + } + } +} + +// From fa04d442c1c4e4e5c0116750251545fd194159e1 Mon Sep 17 00:00:00 2001 From: Roma Marusyk Date: Fri, 3 Jan 2020 00:40:13 +0200 Subject: [PATCH 05/11] Combine all from parts methods into single class. --- ...qlServerDateFromPartsFunctionTranslator.cs | 42 ------- ...verDateTime2FromPartsFunctionTranslator.cs | 44 -------- ...rverDateTimeFromPartsFunctionTranslator.cs | 44 -------- ...teTimeOffsetFromPartsFunctionTranslator.cs | 44 -------- .../SqlServerFromPartsFunctionTranslator.cs | 105 ++++++++++++++++++ .../SqlServerMethodCallTranslatorProvider.cs | 7 +- ...mallDateTimeFromPartsFunctionTranslator.cs | 44 -------- ...qlServerTimeFromPartsFunctionTranslator.cs | 44 -------- 8 files changed, 106 insertions(+), 268 deletions(-) delete mode 100644 src/EFCore.SqlServer/Query/Internal/SqlServerDateFromPartsFunctionTranslator.cs delete mode 100644 src/EFCore.SqlServer/Query/Internal/SqlServerDateTime2FromPartsFunctionTranslator.cs delete mode 100644 src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeFromPartsFunctionTranslator.cs delete mode 100644 src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeOffsetFromPartsFunctionTranslator.cs create mode 100644 src/EFCore.SqlServer/Query/Internal/SqlServerFromPartsFunctionTranslator.cs delete mode 100644 src/EFCore.SqlServer/Query/Internal/SqlServerSmallDateTimeFromPartsFunctionTranslator.cs delete mode 100644 src/EFCore.SqlServer/Query/Internal/SqlServerTimeFromPartsFunctionTranslator.cs diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerDateFromPartsFunctionTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerDateFromPartsFunctionTranslator.cs deleted file mode 100644 index a21d3eb3aae..00000000000 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerDateFromPartsFunctionTranslator.cs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using JetBrains.Annotations; -using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -using Microsoft.EntityFrameworkCore.Storage; - -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal -{ - public class SqlServerDateFromPartsFunctionTranslator : IMethodCallTranslator - { - private readonly ISqlExpressionFactory _sqlExpressionFactory; - private readonly IRelationalTypeMappingSource _typeMappingSource; - - private static readonly MethodInfo _methodInfo = typeof(SqlServerDbFunctionsExtensions) - .GetRuntimeMethod(nameof(SqlServerDbFunctionsExtensions.DateFromParts), new[] { typeof(DbFunctions), typeof(int), typeof(int), typeof(int) }); - - public SqlServerDateFromPartsFunctionTranslator( - [NotNull] ISqlExpressionFactory sqlExpressionFactory, - [NotNull] IRelationalTypeMappingSource typeMappingSource) - { - _sqlExpressionFactory = sqlExpressionFactory; - _typeMappingSource = typeMappingSource; - } - - public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) - { - return _methodInfo.Equals(method) - ? _sqlExpressionFactory.Function( - "DATEFROMPARTS", - arguments.Skip(1), - _methodInfo.ReturnType, - _typeMappingSource.FindMapping(typeof(DateTime), "datetime")) - : null; - } - } -} diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerDateTime2FromPartsFunctionTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerDateTime2FromPartsFunctionTranslator.cs deleted file mode 100644 index aa8b5491855..00000000000 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerDateTime2FromPartsFunctionTranslator.cs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using JetBrains.Annotations; -using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -using Microsoft.EntityFrameworkCore.Storage; - -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal -{ - public class SqlServerDateTime2FromPartsFunctionTranslator : IMethodCallTranslator - { - private readonly ISqlExpressionFactory _sqlExpressionFactory; - private readonly IRelationalTypeMappingSource _typeMappingSource; - - private static readonly MethodInfo _methodInfo = typeof(SqlServerDbFunctionsExtensions) - .GetRuntimeMethod(nameof(SqlServerDbFunctionsExtensions.DateTime2FromParts), new[] { typeof(DbFunctions), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int) }); - - public SqlServerDateTime2FromPartsFunctionTranslator( - [NotNull] ISqlExpressionFactory sqlExpressionFactory, - [NotNull] IRelationalTypeMappingSource typeMappingSource) - { - _sqlExpressionFactory = sqlExpressionFactory; - _typeMappingSource = typeMappingSource; - } - - public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) - { - return _methodInfo.Equals(method) - ? _sqlExpressionFactory.Function( - "DATETIME2FROMPARTS", - arguments.Skip(1), - _methodInfo.ReturnType, - _typeMappingSource.FindMapping(typeof(DateTime), "datetime")) - : null; - } - } -} - -// diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeFromPartsFunctionTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeFromPartsFunctionTranslator.cs deleted file mode 100644 index f0e8a2845b4..00000000000 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeFromPartsFunctionTranslator.cs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using JetBrains.Annotations; -using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -using Microsoft.EntityFrameworkCore.Storage; - -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal -{ - public class SqlServerDateTimeFromPartsFunctionTranslator : IMethodCallTranslator - { - private readonly ISqlExpressionFactory _sqlExpressionFactory; - private readonly IRelationalTypeMappingSource _typeMappingSource; - - private static readonly MethodInfo _methodInfo = typeof(SqlServerDbFunctionsExtensions) - .GetRuntimeMethod(nameof(SqlServerDbFunctionsExtensions.DateTimeFromParts), new[] { typeof(DbFunctions), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int) }); - - public SqlServerDateTimeFromPartsFunctionTranslator( - [NotNull] ISqlExpressionFactory sqlExpressionFactory, - [NotNull] IRelationalTypeMappingSource typeMappingSource) - { - _sqlExpressionFactory = sqlExpressionFactory; - _typeMappingSource = typeMappingSource; - } - - public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) - { - return _methodInfo.Equals(method) - ? _sqlExpressionFactory.Function( - "DATETIMEFROMPARTS", - arguments.Skip(1), - _methodInfo.ReturnType, - _typeMappingSource.FindMapping(typeof(DateTime), "datetime")) - : null; - } - } -} - -// diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeOffsetFromPartsFunctionTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeOffsetFromPartsFunctionTranslator.cs deleted file mode 100644 index 9d863c3c148..00000000000 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeOffsetFromPartsFunctionTranslator.cs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using JetBrains.Annotations; -using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -using Microsoft.EntityFrameworkCore.Storage; - -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal -{ - public class SqlServerDateTimeOffsetFromPartsFunctionTranslator : IMethodCallTranslator - { - private readonly ISqlExpressionFactory _sqlExpressionFactory; - private readonly IRelationalTypeMappingSource _typeMappingSource; - - private static readonly MethodInfo _methodInfo = typeof(SqlServerDbFunctionsExtensions) - .GetRuntimeMethod(nameof(SqlServerDbFunctionsExtensions.DateTimeOffsetFromParts), new[] { typeof(DbFunctions), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int) }); - - public SqlServerDateTimeOffsetFromPartsFunctionTranslator( - [NotNull] ISqlExpressionFactory sqlExpressionFactory, - [NotNull] IRelationalTypeMappingSource typeMappingSource) - { - _sqlExpressionFactory = sqlExpressionFactory; - _typeMappingSource = typeMappingSource; - } - - public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) - { - return _methodInfo.Equals(method) - ? _sqlExpressionFactory.Function( - "DATETIMEOFFSETFROMPARTS", - arguments.Skip(1), - _methodInfo.ReturnType, - _typeMappingSource.FindMapping(typeof(DateTime), "datetime")) - : null; - } - } -} - -// diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerFromPartsFunctionTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerFromPartsFunctionTranslator.cs new file mode 100644 index 00000000000..fb4f8209228 --- /dev/null +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerFromPartsFunctionTranslator.cs @@ -0,0 +1,105 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Storage; + +namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal +{ + public class SqlServerFromPartsFunctionTranslator : IMethodCallTranslator + { + private readonly ISqlExpressionFactory _sqlExpressionFactory; + private readonly IRelationalTypeMappingSource _typeMappingSource; + + private static readonly MethodInfo _dateFromPartsMethodInfo = typeof(SqlServerDbFunctionsExtensions) + .GetRuntimeMethod(nameof(SqlServerDbFunctionsExtensions.DateFromParts), new[] { typeof(DbFunctions), typeof(int), typeof(int), typeof(int) }); + + private static readonly MethodInfo _dateTimeFromPartsMethodInfo = typeof(SqlServerDbFunctionsExtensions) + .GetRuntimeMethod(nameof(SqlServerDbFunctionsExtensions.DateTimeFromParts), new[] { typeof(DbFunctions), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int) }); + + private static readonly MethodInfo _dateTime2FromPartsMethodInfo = typeof(SqlServerDbFunctionsExtensions) + .GetRuntimeMethod(nameof(SqlServerDbFunctionsExtensions.DateTime2FromParts), new[] { typeof(DbFunctions), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int) }); + + private static readonly MethodInfo _dateTimeOffsetFromPartsMethodInfo = typeof(SqlServerDbFunctionsExtensions) + .GetRuntimeMethod(nameof(SqlServerDbFunctionsExtensions.DateTimeOffsetFromParts), new[] { typeof(DbFunctions), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int) }); + + private static readonly MethodInfo _smallDateTimeFromPartsMethodInfo = typeof(SqlServerDbFunctionsExtensions) + .GetRuntimeMethod(nameof(SqlServerDbFunctionsExtensions.SmallDateTimeFromParts), new[] { typeof(DbFunctions), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int) }); + + private static readonly MethodInfo _timeFromPartsMethodInfo = typeof(SqlServerDbFunctionsExtensions) + .GetRuntimeMethod(nameof(SqlServerDbFunctionsExtensions.TimeFromParts), new[] { typeof(DbFunctions), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int) }); + + public SqlServerFromPartsFunctionTranslator( + [NotNull] ISqlExpressionFactory sqlExpressionFactory, + [NotNull] IRelationalTypeMappingSource typeMappingSource) + { + _sqlExpressionFactory = sqlExpressionFactory; + _typeMappingSource = typeMappingSource; + } + + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) + { + if (_dateFromPartsMethodInfo.Equals(method)) + { + return _sqlExpressionFactory.Function( + "DATEFROMPARTS", + arguments.Skip(1), + _dateFromPartsMethodInfo.ReturnType, + _typeMappingSource.FindMapping(typeof(DateTime), "date")); + } + + if (_dateTimeFromPartsMethodInfo.Equals(method)) + { + return _sqlExpressionFactory.Function( + "DATETIMEFROMPARTS", + arguments.Skip(1), + _dateTimeFromPartsMethodInfo.ReturnType, + _typeMappingSource.FindMapping(typeof(DateTime), "datetime")); + } + + if (_dateTime2FromPartsMethodInfo.Equals(method)) + { + return _sqlExpressionFactory.Function( + "DATETIME2FROMPARTS", + arguments.Skip(1), + _dateTime2FromPartsMethodInfo.ReturnType, + _typeMappingSource.FindMapping(typeof(DateTime), "datetime2")); + } + + if (_dateTimeOffsetFromPartsMethodInfo.Equals(method)) + { + return _sqlExpressionFactory.Function( + "DATETIMEOFFSETFROMPARTS", + arguments.Skip(1), + _dateTimeOffsetFromPartsMethodInfo.ReturnType, + _typeMappingSource.FindMapping(typeof(DateTime), "datetimeoffset")); + } + + if (_smallDateTimeFromPartsMethodInfo.Equals(method)) + { + return _sqlExpressionFactory.Function( + "SMALLDATETIMEFROMPARTS", + arguments.Skip(1), + _smallDateTimeFromPartsMethodInfo.ReturnType, + _typeMappingSource.FindMapping(typeof(DateTime), "smalldatetime")); + } + + if (_timeFromPartsMethodInfo.Equals(method)) + { + return _sqlExpressionFactory.Function( + "TIMEFROMPARTS", + arguments.Skip(1), + _timeFromPartsMethodInfo.ReturnType, + _typeMappingSource.FindMapping(typeof(DateTime), "time")); + } + + return null; + } + } +} diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerMethodCallTranslatorProvider.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerMethodCallTranslatorProvider.cs index 447251a937c..502db911571 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerMethodCallTranslatorProvider.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerMethodCallTranslatorProvider.cs @@ -19,19 +19,14 @@ public SqlServerMethodCallTranslatorProvider([NotNull] RelationalMethodCallTrans new SqlServerByteArrayMethodTranslator(sqlExpressionFactory), new SqlServerConvertTranslator(sqlExpressionFactory), new SqlServerDateDiffFunctionsTranslator(sqlExpressionFactory), - new SqlServerDateFromPartsFunctionTranslator(sqlExpressionFactory, typeMappingSource), - new SqlServerDateTime2FromPartsFunctionTranslator(sqlExpressionFactory, typeMappingSource), - new SqlServerDateTimeFromPartsFunctionTranslator(sqlExpressionFactory, typeMappingSource), new SqlServerDateTimeMethodTranslator(sqlExpressionFactory), - new SqlServerDateTimeOffsetFromPartsFunctionTranslator(sqlExpressionFactory, typeMappingSource), + new SqlServerFromPartsFunctionTranslator(sqlExpressionFactory, typeMappingSource), new SqlServerFullTextSearchFunctionsTranslator(sqlExpressionFactory), new SqlServerIsDateFunctionTranslator(sqlExpressionFactory), new SqlServerMathTranslator(sqlExpressionFactory), new SqlServerNewGuidTranslator(sqlExpressionFactory), new SqlServerObjectToStringTranslator(sqlExpressionFactory), - new SqlServerSmallDateTimeFromPartsFunctionTranslator(sqlExpressionFactory, typeMappingSource), new SqlServerStringMethodTranslator(sqlExpressionFactory), - new SqlServerTimeFromPartsFunctionTranslator(sqlExpressionFactory, typeMappingSource) }); } } diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerSmallDateTimeFromPartsFunctionTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerSmallDateTimeFromPartsFunctionTranslator.cs deleted file mode 100644 index 00c33468fe9..00000000000 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerSmallDateTimeFromPartsFunctionTranslator.cs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using JetBrains.Annotations; -using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -using Microsoft.EntityFrameworkCore.Storage; - -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal -{ - public class SqlServerSmallDateTimeFromPartsFunctionTranslator : IMethodCallTranslator - { - private readonly ISqlExpressionFactory _sqlExpressionFactory; - private readonly IRelationalTypeMappingSource _typeMappingSource; - - private static readonly MethodInfo _methodInfo = typeof(SqlServerDbFunctionsExtensions) - .GetRuntimeMethod(nameof(SqlServerDbFunctionsExtensions.SmallDateTimeFromParts), new[] { typeof(DbFunctions), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int) }); - - public SqlServerSmallDateTimeFromPartsFunctionTranslator( - [NotNull] ISqlExpressionFactory sqlExpressionFactory, - [NotNull] IRelationalTypeMappingSource typeMappingSource) - { - _sqlExpressionFactory = sqlExpressionFactory; - _typeMappingSource = typeMappingSource; - } - - public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) - { - return _methodInfo.Equals(method) - ? _sqlExpressionFactory.Function( - "SMALLDATETIMEFROMPARTS", - arguments.Skip(1), - _methodInfo.ReturnType, - _typeMappingSource.FindMapping(typeof(DateTime), "datetime")) - : null; - } - } -} - -// diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerTimeFromPartsFunctionTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerTimeFromPartsFunctionTranslator.cs deleted file mode 100644 index a31fcb34ce0..00000000000 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerTimeFromPartsFunctionTranslator.cs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using JetBrains.Annotations; -using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -using Microsoft.EntityFrameworkCore.Storage; - -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal -{ - public class SqlServerTimeFromPartsFunctionTranslator : IMethodCallTranslator - { - private readonly ISqlExpressionFactory _sqlExpressionFactory; - private readonly IRelationalTypeMappingSource _typeMappingSource; - - private static readonly MethodInfo _methodInfo = typeof(SqlServerDbFunctionsExtensions) - .GetRuntimeMethod(nameof(SqlServerDbFunctionsExtensions.TimeFromParts), new[] { typeof(DbFunctions), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int) }); - - public SqlServerTimeFromPartsFunctionTranslator( - [NotNull] ISqlExpressionFactory sqlExpressionFactory, - [NotNull] IRelationalTypeMappingSource typeMappingSource) - { - _sqlExpressionFactory = sqlExpressionFactory; - _typeMappingSource = typeMappingSource; - } - - public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) - { - return _methodInfo.Equals(method) - ? _sqlExpressionFactory.Function( - "TIMEFROMPARTS", - arguments.Skip(1), - _methodInfo.ReturnType, - _typeMappingSource.FindMapping(typeof(DateTime), "datetime")) - : null; - } - } -} - -// From 123cab04a2dda972d964dc4ff66b632c13ed930a Mon Sep 17 00:00:00 2001 From: Roma Marusyk Date: Fri, 3 Jan 2020 01:05:22 +0200 Subject: [PATCH 06/11] Fix tests --- .../Query/NorthwindDbFunctionsQuerySqlServerTest.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindDbFunctionsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindDbFunctionsQuerySqlServerTest.cs index e401ad751d7..1bb6125a886 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindDbFunctionsQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindDbFunctionsQuerySqlServerTest.cs @@ -770,7 +770,7 @@ public virtual void DateFromParts_constant_compare() AssertSql( @"SELECT COUNT(*) FROM [Orders] AS [o] -WHERE '2018-12-29T00:00:00.000' > DATEFROMPARTS(DATEPART(year, GETDATE()), 12, 31)"); +WHERE '2018-12-29' > DATEFROMPARTS(DATEPART(year, GETDATE()), 12, 31)"); } } @@ -786,13 +786,13 @@ public virtual void DateFromParts_compare_with_local_variable() Assert.Equal(0, count); AssertSql( - @$"@__dateTime_0='1919-12-12T00:00:00' (DbType = DateTime) -@__dateTime_Month_2='12' -@__dateTime_Day_3='12' + @$"@__date_0='1919-12-12' (DbType = Date) +@__date_Month_2='12' +@__date_Day_3='12' SELECT COUNT(*) FROM [Orders] AS [o] -WHERE @__dateTime_0 > DATEFROMPARTS(DATEPART(year, GETDATE()), @__dateTime_Month_2, @__dateTime_Day_3)"); +WHERE @__date_0 > DATEFROMPARTS(DATEPART(year, GETDATE()), @__date_Month_2, @__date_Day_3)"); } } From f60ff10582cf57607302ae61178c4a86c0d1e719 Mon Sep 17 00:00:00 2001 From: Roma Marusyk Date: Fri, 3 Jan 2020 01:57:21 +0200 Subject: [PATCH 07/11] Fix tests --- .../Query/NorthwindDbFunctionsQuerySqlServerTest.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindDbFunctionsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindDbFunctionsQuerySqlServerTest.cs index 1bb6125a886..4f9b1771982 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindDbFunctionsQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindDbFunctionsQuerySqlServerTest.cs @@ -777,11 +777,11 @@ FROM [Orders] AS [o] [ConditionalFact] public virtual void DateFromParts_compare_with_local_variable() { - var dateTime = new DateTime(1919, 12, 12); + var date = new DateTime(1919, 12, 12); using (var context = CreateContext()) { var count = context.Orders - .Count(c => dateTime > EF.Functions.DateFromParts(DateTime.Now.Year, dateTime.Month, dateTime.Day)); + .Count(c => date.Date > EF.Functions.DateFromParts(DateTime.Now.Year, date.Month, date.Day)); Assert.Equal(0, count); From f4880e9db0e1e2c91a1e7b852831f2c1b1e1aba2 Mon Sep 17 00:00:00 2001 From: Roma Marusyk Date: Sun, 5 Jan 2020 18:48:24 +0200 Subject: [PATCH 08/11] Add tests for DATETIME2FROMPARTS --- .../NorthwindDbFunctionsQuerySqlServerTest.cs | 65 ++++++++++++++++++- 1 file changed, 63 insertions(+), 2 deletions(-) diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindDbFunctionsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindDbFunctionsQuerySqlServerTest.cs index 4f9b1771982..a3c4837807b 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindDbFunctionsQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindDbFunctionsQuerySqlServerTest.cs @@ -781,12 +781,12 @@ public virtual void DateFromParts_compare_with_local_variable() using (var context = CreateContext()) { var count = context.Orders - .Count(c => date.Date > EF.Functions.DateFromParts(DateTime.Now.Year, date.Month, date.Day)); + .Count(c => date > EF.Functions.DateFromParts(DateTime.Now.Year, date.Month, date.Day)); Assert.Equal(0, count); AssertSql( - @$"@__date_0='1919-12-12' (DbType = Date) + @$"@__date_0='1919-12-12T00:00:00' (DbType = Date) @__date_Month_2='12' @__date_Day_3='12' @@ -796,6 +796,67 @@ FROM [Orders] AS [o] } } + [ConditionalFact] + public virtual void DateTime2FromParts_column_compare() + { + using (var context = CreateContext()) + { + var count = context.Orders + .Count(c => c.OrderDate > EF.Functions.DateTime2FromParts(DateTime.Now.Year, 12, 31, 23, 59, 59, 999, 3)); + + Assert.Equal(0, count); + + AssertSql( + @"SELECT COUNT(*) +FROM [Orders] AS [o] +WHERE [o].[OrderDate] > DATETIME2FROMPARTS(DATEPART(year, GETDATE()), 12, 31, 23, 59, 59, 999, 3)"); + } + } + + [ConditionalFact] + public virtual void DateTime2FromParts_constant_compare() + { + using (var context = CreateContext()) + { + var count = context.Orders + .Count(c => new DateTime(2018, 12, 29, 23, 20, 40) > EF.Functions.DateTime2FromParts(DateTime.Now.Year, 12, 31, 23, 59, 59, 9999999, 7)); + + Assert.Equal(0, count); + + AssertSql( + @"SELECT COUNT(*) +FROM [Orders] AS [o] +WHERE '2018-12-29T23:20:40.0000000' > DATETIME2FROMPARTS(DATEPART(year, GETDATE()), 12, 31, 23, 59, 59, 9999999, 7)"); + } + } + + [ConditionalFact] + public virtual void DateTime2FromParts_compare_with_local_variable() + { + var dateTime = new DateTime(1919, 12, 12, 10, 20, 15); + int fractions = 9999999; + using (var context = CreateContext()) + { + var count = context.Orders + .Count(c => dateTime > EF.Functions.DateTime2FromParts(DateTime.Now.Year, dateTime.Month, dateTime.Day, dateTime.Hour, dateTime.Minute, dateTime.Second, fractions, 7)); + + Assert.Equal(0, count); + + AssertSql( + @$"@__dateTime_0='1919-12-12T10:20:15' +@__dateTime_Month_2='12' +@__dateTime_Day_3='12' +@__dateTime_Hour_4='10' +@__dateTime_Minute_5='20' +@__dateTime_Second_6='15' +@__fractions_7='9999999' + +SELECT COUNT(*) +FROM [Orders] AS [o] +WHERE @__dateTime_0 > DATETIME2FROMPARTS(DATEPART(year, GETDATE()), @__dateTime_Month_2, @__dateTime_Day_3, @__dateTime_Hour_4, @__dateTime_Minute_5, @__dateTime_Second_6, @__fractions_7, 7)"); + } + } + private void AssertSql(params string[] expected) => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); } From 4951c6d8e55170030b90fbb1f7a77de708bbbeed Mon Sep 17 00:00:00 2001 From: Roma Marusyk Date: Sun, 5 Jan 2020 21:31:15 +0200 Subject: [PATCH 09/11] Add tests and fix return type for functions --- .../SqlServerDbFunctionsExtensions.cs | 4 +- .../SqlServerFromPartsFunctionTranslator.cs | 4 +- .../NorthwindDbFunctionsQuerySqlServerTest.cs | 123 ++++++++++++++++++ 3 files changed, 127 insertions(+), 4 deletions(-) diff --git a/src/EFCore.SqlServer/Extensions/SqlServerDbFunctionsExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerDbFunctionsExtensions.cs index 18aa22e0c80..673c1c9ee28 100644 --- a/src/EFCore.SqlServer/Extensions/SqlServerDbFunctionsExtensions.cs +++ b/src/EFCore.SqlServer/Extensions/SqlServerDbFunctionsExtensions.cs @@ -1066,7 +1066,7 @@ public static DateTime DateTime2FromParts( /// The minute portion of the time zone offset. /// The precision of the datetime2 value. /// New instance of the structure to the specified year, month, day, hour, minute, second, fractions, hourOffset, minuteOffset and precision. - public static DateTime DateTimeOffsetFromParts( + public static DateTimeOffset DateTimeOffsetFromParts( [CanBeNull] this DbFunctions _, int year, int month, @@ -1111,7 +1111,7 @@ public static DateTime SmallDateTimeFromParts( /// The fractional seconds. /// The precision of the time value. /// New instance of the structure to the specified hour, minute, second, fractions, and precision. - public static DateTime TimeFromParts( + public static TimeSpan TimeFromParts( [CanBeNull] this DbFunctions _, int hour, int minute, diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerFromPartsFunctionTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerFromPartsFunctionTranslator.cs index fb4f8209228..ad7c24bea29 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerFromPartsFunctionTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerFromPartsFunctionTranslator.cs @@ -78,7 +78,7 @@ public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method "DATETIMEOFFSETFROMPARTS", arguments.Skip(1), _dateTimeOffsetFromPartsMethodInfo.ReturnType, - _typeMappingSource.FindMapping(typeof(DateTime), "datetimeoffset")); + _typeMappingSource.FindMapping(typeof(DateTimeOffset), "datetimeoffset")); } if (_smallDateTimeFromPartsMethodInfo.Equals(method)) @@ -96,7 +96,7 @@ public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method "TIMEFROMPARTS", arguments.Skip(1), _timeFromPartsMethodInfo.ReturnType, - _typeMappingSource.FindMapping(typeof(DateTime), "time")); + _typeMappingSource.FindMapping(typeof(TimeSpan), "time")); } return null; diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindDbFunctionsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindDbFunctionsQuerySqlServerTest.cs index a3c4837807b..e5ba09455cf 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindDbFunctionsQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindDbFunctionsQuerySqlServerTest.cs @@ -857,6 +857,129 @@ FROM [Orders] AS [o] } } + [ConditionalFact] + public virtual void DateTimeOffsetFromParts_column_compare() + { + using (var context = CreateContext()) + { + var count = context.Orders + .Count(c => c.OrderDate > EF.Functions.DateTimeOffsetFromParts(DateTime.Now.Year, 12, 31, 23, 59, 59, 5, 12, 30, 1)); + + Assert.Equal(0, count); + + AssertSql( + @"SELECT COUNT(*) +FROM [Orders] AS [o] +WHERE CAST([o].[OrderDate] AS datetimeoffset) > DATETIMEOFFSETFROMPARTS(DATEPART(year, GETDATE()), 12, 31, 23, 59, 59, 5, 12, 30, 1)"); + } + } + + [ConditionalFact] + public virtual void DateTimeOffsetFromParts_constant_compare() + { + using (var context = CreateContext()) + { + var count = context.Orders + .Count(c => new DateTimeOffset(2018, 12, 29, 23, 20, 40, new TimeSpan(1, 0, 0)) > EF.Functions.DateTimeOffsetFromParts(DateTime.Now.Year, 12, 31, 23, 59, 59, 50, 1, 0, 7)); + + Assert.Equal(0, count); + + AssertSql( + @"SELECT COUNT(*) +FROM [Orders] AS [o] +WHERE '2018-12-29T23:20:40.0000000+01:00' > DATETIMEOFFSETFROMPARTS(DATEPART(year, GETDATE()), 12, 31, 23, 59, 59, 50, 1, 0, 7)"); + } + } + + [ConditionalFact] + public virtual void DateTimeOffsetFromParts_compare_with_local_variable() + { + var dateTimeOffset = new DateTimeOffset(1919, 12, 12, 10, 20, 15, new TimeSpan(1, 30, 0)); + int fractions = 5; + int hourOffset = 1; + int minuteOffset = 30; + using (var context = CreateContext()) + { + var count = context.Orders + .Count(c => dateTimeOffset > EF.Functions.DateTimeOffsetFromParts(DateTime.Now.Year, dateTimeOffset.Month, dateTimeOffset.Day, dateTimeOffset.Hour, dateTimeOffset.Minute, dateTimeOffset.Second, fractions, hourOffset, minuteOffset, 7)); + + Assert.Equal(0, count); + + AssertSql( + @$"@__dateTimeOffset_0='1919-12-12T10:20:15.0000000+01:30' +@__dateTimeOffset_Month_2='12' +@__dateTimeOffset_Day_3='12' +@__dateTimeOffset_Hour_4='10' +@__dateTimeOffset_Minute_5='20' +@__dateTimeOffset_Second_6='15' +@__fractions_7='5' +@__hourOffset_8='1' +@__minuteOffset_9='30' + +SELECT COUNT(*) +FROM [Orders] AS [o] +WHERE @__dateTimeOffset_0 > DATETIMEOFFSETFROMPARTS(DATEPART(year, GETDATE()), @__dateTimeOffset_Month_2, @__dateTimeOffset_Day_3, @__dateTimeOffset_Hour_4, @__dateTimeOffset_Minute_5, @__dateTimeOffset_Second_6, @__fractions_7, @__hourOffset_8, @__minuteOffset_9, 7)"); + } + } + + [ConditionalFact] + public virtual void SmallDateTimeFromParts_column_compare() + { + using (var context = CreateContext()) + { + var count = context.Orders + .Count(c => c.OrderDate > EF.Functions.SmallDateTimeFromParts(DateTime.Now.Year, 12, 31, 12, 59)); + + Assert.Equal(0, count); + + AssertSql( + @"SELECT COUNT(*) +FROM [Orders] AS [o] +WHERE [o].[OrderDate] > SMALLDATETIMEFROMPARTS(DATEPART(year, GETDATE()), 12, 31, 12, 59)"); + } + } + + [ConditionalFact] + public virtual void SmallDateTimeFromParts_constant_compare() + { + using (var context = CreateContext()) + { + var count = context.Orders + .Count(c => new DateTime(2018, 12, 29, 23, 20, 0) > EF.Functions.SmallDateTimeFromParts(DateTime.Now.Year, 12, 31, 12, 59)); + + Assert.Equal(0, count); + + AssertSql( + @"SELECT COUNT(*) +FROM [Orders] AS [o] +WHERE '2018-12-29T23:20:00' > SMALLDATETIMEFROMPARTS(DATEPART(year, GETDATE()), 12, 31, 12, 59)"); + } + } + + [ConditionalFact] + public virtual void SmallDateTimeFromParts_compare_with_local_variable() + { + var dateTime = new DateTime(1919, 12, 12, 23, 20, 0); + using (var context = CreateContext()) + { + var count = context.Orders + .Count(c => dateTime > EF.Functions.SmallDateTimeFromParts(DateTime.Now.Year, dateTime.Month, dateTime.Day, dateTime.Hour, dateTime.Minute)); + + Assert.Equal(0, count); + + AssertSql( + @$"@__dateTime_0='1919-12-12T23:20:00' (DbType = DateTime) +@__dateTime_Month_2='12' +@__dateTime_Day_3='12' +@__dateTime_Hour_4='23' +@__dateTime_Minute_5='20' + +SELECT COUNT(*) +FROM [Orders] AS [o] +WHERE @__dateTime_0 > SMALLDATETIMEFROMPARTS(DATEPART(year, GETDATE()), @__dateTime_Month_2, @__dateTime_Day_3, @__dateTime_Hour_4, @__dateTime_Minute_5)"); + } + } + private void AssertSql(params string[] expected) => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); } From fb84a502e4372dff8f18a55a8468cf530dfc7048 Mon Sep 17 00:00:00 2001 From: Roma Marusyk Date: Sun, 5 Jan 2020 22:56:30 +0200 Subject: [PATCH 10/11] Fix docs --- .../Extensions/SqlServerDbFunctionsExtensions.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/EFCore.SqlServer/Extensions/SqlServerDbFunctionsExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerDbFunctionsExtensions.cs index 673c1c9ee28..3b3ff830d82 100644 --- a/src/EFCore.SqlServer/Extensions/SqlServerDbFunctionsExtensions.cs +++ b/src/EFCore.SqlServer/Extensions/SqlServerDbFunctionsExtensions.cs @@ -1051,7 +1051,7 @@ public static DateTime DateTime2FromParts( => throw new InvalidOperationException(SqlServerStrings.FunctionOnClient(nameof(DateTime2FromParts))); /// - /// Initializes a new instance of the structure to the specified year, month, day, hour, minute, second, fractions, hourOffset, minuteOffset and precision. + /// Initializes a new instance of the structure to the specified year, month, day, hour, minute, second, fractions, hourOffset, minuteOffset and precision. /// Corresponds to the SQL Server's DATETIMEOFFSETFROMPARTS (year, month, day, hour, minute, seconds, fractions, hour_offset, minute_offset, precision). /// /// The DbFunctions instance. @@ -1065,7 +1065,7 @@ public static DateTime DateTime2FromParts( /// The hour portion of the time zone offset. /// The minute portion of the time zone offset. /// The precision of the datetime2 value. - /// New instance of the structure to the specified year, month, day, hour, minute, second, fractions, hourOffset, minuteOffset and precision. + /// New instance of the structure to the specified year, month, day, hour, minute, second, fractions, hourOffset, minuteOffset and precision. public static DateTimeOffset DateTimeOffsetFromParts( [CanBeNull] this DbFunctions _, int year, @@ -1101,7 +1101,7 @@ public static DateTime SmallDateTimeFromParts( => throw new InvalidOperationException(SqlServerStrings.FunctionOnClient(nameof(SmallDateTimeFromParts))); /// - /// Initializes a new instance of the structure to the specified hour, minute, second, fractions, and precision. + /// Initializes a new instance of the structure to the specified hour, minute, second, fractions, and precision. /// Corresponds to the SQL Server's TIMEFROMPARTS (hour, minute, seconds, fractions, precision). /// /// The DbFunctions instance. @@ -1110,7 +1110,7 @@ public static DateTime SmallDateTimeFromParts( /// The seconds (0 through 59). /// The fractional seconds. /// The precision of the time value. - /// New instance of the structure to the specified hour, minute, second, fractions, and precision. + /// New instance of the structure to the specified hour, minute, second, fractions, and precision. public static TimeSpan TimeFromParts( [CanBeNull] this DbFunctions _, int hour, From 7a0c202fc2896212e1ab3eea4e3475c61572a608 Mon Sep 17 00:00:00 2001 From: Roma Marusyk Date: Wed, 8 Jan 2020 02:55:57 +0200 Subject: [PATCH 11/11] Add test for TIMEFROMPARTS --- .../SqlServerDbFunctionsExtensions.cs | 16 ++++++++-------- .../NorthwindDbFunctionsQuerySqlServerTest.cs | 17 +++++++++++++++++ 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/EFCore.SqlServer/Extensions/SqlServerDbFunctionsExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerDbFunctionsExtensions.cs index 3b3ff830d82..7f0204fabb5 100644 --- a/src/EFCore.SqlServer/Extensions/SqlServerDbFunctionsExtensions.cs +++ b/src/EFCore.SqlServer/Extensions/SqlServerDbFunctionsExtensions.cs @@ -1035,8 +1035,8 @@ public static DateTime DateFromParts( /// The hours (0 through 23). /// The minutes (0 through 59). /// The seconds (0 through 59). - /// The fractional seconds. - /// The precision of the datetime2 value. + /// The fractional seconds (0 through 9999999). + /// The precision of the datetime2 value (0 through 7). /// New instance of the structure to the specified year, month, day, hour, minute, second, fractions, and precision. public static DateTime DateTime2FromParts( [CanBeNull] this DbFunctions _, @@ -1061,10 +1061,10 @@ public static DateTime DateTime2FromParts( /// The hours (0 through 23). /// The minutes (0 through 59). /// The seconds (0 through 59). - /// The fractional seconds. - /// The hour portion of the time zone offset. - /// The minute portion of the time zone offset. - /// The precision of the datetime2 value. + /// The fractional seconds (0 through 9999999). + /// The hour portion of the time zone offset (-14 through +14). + /// The minute portion of the time zone offset (0 or 30). + /// The precision of the datetimeoffset value (0 through 7). /// New instance of the structure to the specified year, month, day, hour, minute, second, fractions, hourOffset, minuteOffset and precision. public static DateTimeOffset DateTimeOffsetFromParts( [CanBeNull] this DbFunctions _, @@ -1108,8 +1108,8 @@ public static DateTime SmallDateTimeFromParts( /// The hours (0 through 23). /// The minutes (0 through 59). /// The seconds (0 through 59). - /// The fractional seconds. - /// The precision of the time value. + /// The fractional seconds (0 through 9999999). + /// The precision of the time value (0 through 7). /// New instance of the structure to the specified hour, minute, second, fractions, and precision. public static TimeSpan TimeFromParts( [CanBeNull] this DbFunctions _, diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindDbFunctionsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindDbFunctionsQuerySqlServerTest.cs index e5ba09455cf..5519758014d 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindDbFunctionsQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindDbFunctionsQuerySqlServerTest.cs @@ -980,6 +980,23 @@ FROM [Orders] AS [o] } } + [ConditionalFact] + public virtual void TimeFromParts_constant_compare() + { + using (var context = CreateContext()) + { + var count = context.Orders + .Count(c => new TimeSpan(23, 59, 0) > EF.Functions.TimeFromParts(23, 59, 59, c.OrderID % 60, 2)); + + Assert.Equal(0, count); + + AssertSql( + @"SELECT COUNT(*) +FROM [Orders] AS [o] +WHERE '23:59:00' > TIMEFROMPARTS(23, 59, 59, [o].[OrderID] % 60, 2)"); + } + } + private void AssertSql(params string[] expected) => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); }