RepoDB icon indicating copy to clipboard operation
RepoDB copied to clipboard

Bug: TimeSpan? property data type mapping fails with System.Data.SqlClient

Open cajuncoding opened this issue 4 years ago • 2 comments

Bug Description

When using System.Data.SqlClient with RepoDb Batch Operations (InsertAllAsync, UpdateAllAsync, MergeAllAsync) to batch update data in Sql Server using at TimeSpan? model property an unexpected error occurs.

The properties are TimeSpan? nullable properties on the Model, and the SQL Server columns are time(7) types...

Exception Message:

Failed to convert parameter value from a TimeSpan to a DateTime. Inner Exception: Object must implement IConvertible

Schema and Model:

Please share to us the schema of the table (not actual) that could help us replicate the issue if necessary.

//Sample Model:
public class TestTable {
    public int Id { get; set; }
    public TimeSpan? ItemStartTime{ get; set; }
    public TimeSpan? ItemEndTime{ get; set; }
}
--Sampel DB Schema:
CREATE TABLE [dbo].[TestTable](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [ItemStartTime] [time](7) NULL,
    [ItemEndTime] [time](7) NULL,
 CONSTRAINT [PK__AdwordCa__3214EC07E2A92D2C] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

Library Version: Using latest RepoDB Sql Server Library v1.12.7 and RepoDb.SqlServer v1.1.3

cajuncoding avatar Jun 10 '21 23:06 cajuncoding

Per our conversation on Gitter, our initial discussion yielded the following findings:

  1. Microsoft documentation states for DbType Enum it says DbType.Time (17) -- A type representing a SQL Server DateTime value. If you want to use a SQL Server time value, use Time. And then if you look at SqlDbType Enum it says SqlDbType.Time (32) -- Time data based on a 24-hour clock. Time value range is 00:00:00 through 23:59:59.9999999 with an accuracy of 100 nanoseconds. Corresponds to a SQL Server time value. Of which we expect that the correct mapping to SqlDbType.Time would automatically occur.
  2. This does work as expected with Microsoft.Data.SqlClient, but fails with System.Data.SqlClient.
  3. You were able to successfully reproduce the issue... image

Thanks!

cajuncoding avatar Jun 10 '21 23:06 cajuncoding

Good News: As discussed on Gitter, we cannot easily change the legacy code base from using System.Data.SqlClient (yet; it's on our strategic plan though), however we were able to resolve this with the use of [SystemSqlServerTypeMap(SqlDbType.Time)] attribute on the offending model properties.

Is there a way to do this via Global Type Mapping configuration? Unfortunately I was not able to get it to work with a global configuration via FluentMapper or TypeMapper which would help ensure that it's resolved universally...

cajuncoding avatar Jun 10 '21 23:06 cajuncoding