Description
Describe the bug
When creating a DateTime2 SqlParameter with scale explicitly set to zero, the parameter is sent to the SQL server as datetime2(7)
new SqlParameter("@p1", System.Data.SqlDbType.DateTime2) { Scale = 0};
-> @p1 datetime2(7)
Miss-matched parameter types can cause performance issues in SQL. in addition the use of datetime2(0) instead of datetime2(7) in the database saves 2 bytes per field.
My real world example of this is a table with hundred of millions of rows where the datetime data does not have sub-second precision so we are using datetime2(0) as the data type and that a specific database query does 200-300 times as much IO when using a parameter type of datetime2(7) than datetime2(0).
To reproduce
[Fact]
public async Task DemonstrateBrokenScale()
{
var date = new DateTime(2021, 11, 01, 23, 59, 59, 999);
var dateRoundedToSeconds = date.AddMilliseconds((Math.Round((double)date.Millisecond / 1000) * 1000) - date.Millisecond);
var sqlConnection = new SqlConnection("Data Source=.;Integrated Security=True;");
await sqlConnection.OpenAsync();
await using var command = sqlConnection.CreateCommand();
command.CommandType = System.Data.CommandType.Text;
command.CommandText = "select @p1";
var p1 = new SqlParameter("@p1", System.Data.SqlDbType.DateTime2) { Scale = 0, Value = date };
command.Parameters.Add(p1);
var result = await command.ExecuteScalarAsync();
Assert.Equal(dateRoundedToSeconds, (DateTime)result); //should get back value rounded up to whole seconds (SQL server behaviour)
}
This will produce the following sql:
exec sp_executesql N'select @p1',N'@p1 datetime2(7)',@p1='2021-11-01 23:59:59.9990000'
Expected behavior
it should create a parameter of type datetime2(0), i'm a little unsure if it should round the value or leave that to the server:
exec sp_executesql N'select @p1',N'@p1 datetime2(0)',@p1='2021-11-01 23:59:59.9990000'
or
exec sp_executesql N'select @p1',N'@p1 datetime2(0)',@p1='2021-11-02 00:00:00'
Further technical details
Additional context
I believe this has been a problem for some time and the issue is noted in a comment in the source:
May also be related to #1214