Skip to content

SqlParameter ignores scale when explicitly set to 0 #1380

Closed
@EamonHetherton

Description

@EamonHetherton

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:

// issue: how could a user specify 0 as the actual scale?

May also be related to #1214

Metadata

Metadata

Assignees

No one assigned

    Labels

    Up-for-Grabs 🙌Issues that are ready to be picked up for anyone interested. Please self-assign and remove the label

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions