Oracle.ManagedDataAccess 错误地读取 DST 日期

Posted

技术标签:

【中文标题】Oracle.ManagedDataAccess 错误地读取 DST 日期【英文标题】:Oracle.ManagedDataAccess reads DST dates incorrectly 【发布时间】:2015-03-10 15:30:20 【问题描述】:

我正在编写一个运行在 Oracle 11.2.0.2.0 数据库之上的 .Net 应用程序,该数据库将日期存储在类型为“TIMESTAMP(6) WITH LOCAL TIME ZONE”的列中。如果列中存储了一个日期并且它属于 DST,则在使用 Oracle.ManagedDataAccess 库时会错误地读取该日期。它似乎总是正确地写入/更新日期。此外,在使用 Oracle.DataAccess 库时,它始终正确处理日期。

在我的示例中,我使用时区“America/New_York”和 08/01/2014 12:00:00 的日期/时间。这是一段错误读取日期的代码:

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();

当使用值 08/01/2014 12:00:00 更新列时,将读取为 08/01/2014 11:00:00。如果我使用不属于 DST 的日期(例如 12/01/2014 12:00:00),它会正确读取日期。对此有什么想法吗?我一直在搜索,但没有找到关于这个问题的任何文档。我可能不得不切换回 Oracle.DataAccess,但希望能避免它。提前致谢!

【问题讨论】:

【参考方案1】:

Oracle.ManagedDataAccess 还是很新的,所以你总是会遇到“最新”的错误。

还有其他方法可以定义您当前的会话时区,可能是以下方法之一。

OracleGlobalization类的用法:

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

非常仔细地测试一下,我对OracleGlobalization 的体验非常糟糕。还测试this.Connection.OpenWithNewPassword(...);,而不仅仅是this.Connection.Open();。当我使用OpenWithNewPassword 时,我的应用程序崩溃而没有任何错误(即使在 Visual Studio 中调试时!)

ORA_SDTZ 设置为系统中的环境变量。

在您的注册表中设置时区,它是HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\KEY_YOUR_ORACLE_HOME_NAME\ORA_SDTZ 的字符串值,例如

对于 x64(64 位)应用程序

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\KEY_OraClient11g_home1]
"ORA_SDTZ"="America/New_York"

对于 x86(32 位)应用程序

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\ORACLE\KEY_OraClient11g_home1]
"ORA_SDTZ"="America/New_York"

注意,ODP.NET Managed Driver 不读取任何注册表值,因此这更多是作为其他驱动程序的信息!

【讨论】:

我遇到了同样的问题。第一个想法(OracleGlobalization)不起作用,因为错误已在 .Open() 上引发。 Env 变量似乎没有效果。在我的情况下,注册表项也不是一个选项,因为我在 Linux 中运行 .NET Core。还有其他想法吗?谢谢!

以上是关于Oracle.ManagedDataAccess 错误地读取 DST 日期的主要内容,如果未能解决你的问题,请参考以下文章

Oracle.ManagedDataAccess:TNS:无法解析指定的连接标识符

Oracle.ManagedDataAccess 错误地读取 DST 日期

ManagedDataAccess连数据库

ManagedDataAccess连数据库

C#工具类OracleHelper,基于Oracle.ManagedDataAccess.Client封装

如何使用 Oracle.ManagedDataAccess.EntityFramework 提供程序从不同的架构中选择表?