Oracle.ManagedDataAccess reads DST dates incorrect

2019-04-14 23:55发布

问题:

I am writing a .Net application that runs on top of an Oracle 11.2.0.2.0 database that stores dates in columns of type "TIMESTAMP(6) WITH LOCAL TIME ZONE". When there is a date stored into the column and it falls within DST, the date is read incorrectly when using the Oracle.ManagedDataAccess library. It appears to always write/update dates correctly. Also, when using the Oracle.DataAccess library, it always handles the dates correctly.

In my example I am using timezone 'America/New_York' and date/time of 08/01/2014 12:00:00. Here is a snippet of code that reads the date incorrectly:

IDbConnection cxn = new Oracle.ManagedDataAccess.Client.OracleConnection(ConnStr);
// Using the following library works correctly: 
// IDbConnection cxn = new Oracle.DataAccess.Client.OracleConnection(ConnStr);
cxn.Open();

var cmd = cxn.CreateCommand();
cmd.CommandText = "alter session set time_zone='America/New_York'";
cmd.ExecuteNonQuery();
cmd.CommandText = "SELECT TEST_DATE FROM TEST_TABLE WHERE ROWNUM=1";
return (DateTime)cmd.ExecuteScalar();

When the column is updated with value 08/01/2014 12:00:00, it is read as 08/01/2014 11:00:00. If I use a date that does not fall within DST (such as 12/01/2014 12:00:00), it reads the date correctly. Any ideas on this? I have been searching all over but have not found any documentation on this issue. I may have to switch back to the Oracle.DataAccess, but was hoping to avoid it. Thanks in advance!

回答1:

Oracle.ManagedDataAccess is still quite new, so you also get always the "newest" bugs.

There are others ways to define your current session timezone, maybe one of the following works.

  • Usage of OracleGlobalization class:

    this.Connection = new OracleConnection();
    this.Connection.ConnectionString = ...
    this.Connection.Open();
    OracleGlobalization info = this.Connection.GetSessionInfo();
    info.TimeZone = "America/New_York";
    this.Connection.SetSessionInfo(info);
    

    Test this very carefully, my experience with OracleGlobalization is quite bad. Test also this.Connection.OpenWithNewPassword(...);, not only this.Connection.Open();. When I used OpenWithNewPassword my application was crashing without any error (even while debugging in Visual Studio!)

  • Set ORA_SDTZ as Environment variable in your system.

  • Set timezone in your Registry, it is a String Value for HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\KEY_{YOUR_ORACLE_HOME_NAME}\ORA_SDTZ, e.g.

    For a x64 (64 bit) Application

    Windows Registry Editor Version 5.00
    
    [HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\KEY_OraClient11g_home1]
    "ORA_SDTZ"="America/New_York"
    

    For a x86 (32 bit) Application

    Windows Registry Editor Version 5.00
    
    [HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\ORACLE\KEY_OraClient11g_home1]
    "ORA_SDTZ"="America/New_York"
    

    Note, ODP.NET Managed Driver does not read any Registry values, so this is more as information for other drivers!