Description
According to ODBC documentation, ODBC supports the SQL 2008+ types like datetime2
, date
, time
and datetimeoffset
.
But it seems impossible to use them with System.Data.Odbc
available on MyGet since #19102, excepted Date
. They look unsupported by this ODBC client, although I have the "ODBC Driver 13 for SQL Server" and its "SQL Server Native Client 11.0" driver:
-
Trying to read a
Time
column with aSystem.Data.Odbc
readerGetValue
yields:System.ArgumentException : Unknown SQL type - SS_TIME_EX. at System.Data.Odbc.TypeMap.FromSqlType(SQL_TYPE sqltype) at System.Data.Odbc.OdbcDataReader.GetSqlType(Int32 i) at System.Data.Odbc.OdbcDataReader.GetValue(Int32 i)
-
Trying to read a
Time
column with aSystem.Data.Odbc
readerGetTime
cuts fractional seconds. -
Trying to set a
Time
parameter on anOdbcCommand
cuts its fractional seconds. -
Trying to set a
DateTime2
parameter on anOdbcCommand
yields:System.ArgumentException : No mapping exists from DbType DateTime2 to a known OdbcType. at System.Data.Odbc.TypeMap.FromDbType(DbType dbType) at System.Data.Odbc.OdbcParameter.set_DbType(DbType value)
-
Setting a
DateTimeOffset
parameter yields the same error with just the db-type name accordingly changed. -
Trying to read a
DateTimeOffset
column with aSystem.Data.Odbc
readerGetValue
yields:System.ArgumentException : Unknown SQL type - -155. at System.Data.Odbc.TypeMap.FromSqlType(SQL_TYPE sqltype) at System.Data.Odbc.OdbcDataReader.GetSqlType(Int32 i) at System.Data.Odbc.OdbcDataReader.GetValue(Int32 i)
-
Trying to read a
DateTimeOffset
column with aSystem.Data.Odbc
readerGetDateTime
cuts offset (but preserves fractional seconds (all 7 digits)). -
Checking
OdbcType
enumeration, it does not have types fordatetimeoffset
ordatetime2
. -
Trying to dodge the trouble for
datetime2
by usingDbType.DateTime
instead for parameter:-
Requires to set the parameter scale, otherwise fails with:
System.Data.Odbc.OdbcException : ERROR [22008] [Microsoft][SQL Server Native Client 11.0]Datetime field overflow. Fractional second precision exceeds the scale specified in the parameter binding. at System.Data.Odbc.OdbcCommand.ExecuteReaderObject(CommandBehavior behavior, String method, Boolean needReader, Object[] methodArguments, SQL_API odbcApiMethod) at System.Data.Odbc.OdbcCommand.ExecuteReaderObject(CommandBehavior behavior, String method, Boolean needReader) at System.Data.Odbc.OdbcCommand.ExecuteScalar()
-
When setting the parameter scale to 7, cuts fractional milliseconds even if the column in database is
datetime2
. This gives the one millisecond precision (compared to SQL Serverdatetime
ten thirds of ms precision), butdatetime2
can go down to 100ns. Catching the query with SQL Server Profiler, we can see this:exec sp_executesql N'select count(*) from Types2008 where [DateTime2] = @P1', N'@P1 datetime2','2017-10-26 20:01:55.1630000'
So the value is
datetime2
typed but has its fractional milliseconds zeroed out (yes my original value was not having them already zeroed).By the way this
datetime2
typing causes issues when the underlying table column isdatetime
instead, because it occurs in this case too. It causeswhere
equality conditions to fail matching on two thirds ofdatetime
values. Those ending with3
or7
milliseconds are not considered equal to the "same" value when typeddatetime2
with four trailing zero. Only those ending with 0 millisecond match.
-
Those results were obtained with .Net Core 2.0, System.Data.Odbc 4.5.0-preview1-25829-02, a SQL Server Express 2016, and as connection string:
Driver={SQL Server Native Client 11.0};
Server=.\sql_express;
Database=test;
Trusted_Connection=yes;
Mars_Connection=yes;
Here is a complete gist of tests reproducing those issues.
Those troubles exist with .Net Framework too, and are reported here.