在 c# 中,使用 odp.net,我调用了一个返回游标的 oracle 函数。一些列的类型是“带时区的时间戳”(TSTZ)。如果我直接使用OracleDataAdapter,这些列将转换为 System.DateTime 并且时区信息会丢失。这是预期的行为,建议似乎是使用SafeMapping强制转换为字符串,例如:
dataAdapter.SafeMapping.Add("column_name", typeof(string));
然后我确实将 TSTZ 作为字符串获取,但它使用的格式DD-MON-YYYY HH:MI:SS.FF AM TZR
如下:
23-NOV-12 08.10.12.057868000 PM ASIA/CALCUTTA
我想要的是偏移量(例如格式DD-MON-YYYY HH:MI:SS.FF AM TZH:TZD
如下:
23-NOV-12 08.10.12.057868000 PM +04:30
当我直接查询 oracle 时(比如在 Sql Developer 中),我可以使用
Alter Session Set Nls_Timestamp_Tz_Format='DD-MON-YYYY HH:MI:SS.FF AM TZH:TZM'
得到我想要的格式。使用 odp.net 我尝试在 SetSessionInfo 中设置格式:
connection.Open();
OracleGlobalization glob = connection.GetSessionInfo();
glob.TimeStampTZFormat = "DD-MON-YYYY HH:MI:SS.FF AM TZH:TZM";
connection.SetSessionInfo(glob);
以及alter session
使用相同的连接执行命令,但都没有任何效果。我认为这是因为转换为字符串是在稍后阶段进行的,并且连接设置无效。
有没有其他方法可以让 odp.net 直接为我提供偏移量?我无法更改 oracle db 函数,因此在方法中使用例如 tz_offset 不是一个选项。
如果这是不可能的,将时区字符串转换为偏移量的最佳方法是什么?我目前正在考虑执行
select TZNAME, TZABBREV, tz_offset(TZNAME) as TZOFFSET
from V$TIMEZONE_NAMES
一次建立一个查找表,但如果有更好的选择会很高兴。
我的数据检索代码,包括我尝试过的东西:
using (var connection = new OracleConnection(this.connectionString))
{
connection.Open();
OracleGlobalization glob = connection.GetSessionInfo();
glob.TimeStampTZFormat = "DD-MON-YYYY HH:MI:SS.FF AM TZH:TZM";
connection.SetSessionInfo(glob);
string sql = "ALTER SESSION " +
"SET NLS_TIMESTAMP_TZ_FORMAT = 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"'";
using (var cmd = connection.CreateCommand())
{
cmd.CommandText = sql;
cmd.ExecuteNonQuery();
}
using (var cmd = connection.CreateCommand())
{
cmd.CommandText = "fn_name";
cmd.CommandType = CommandType.StoredProcedure;
cmd.BindByName = false;
var output = cmd.Parameters.Add("return_value", OracleDbType.RefCursor);
output.Direction = ParameterDirection.ReturnValue;
cmd.Parameters.Add("id", id).Direction = ParameterDirection.Input;
using (var dataAdapter = new OracleDataAdapter(cmd))
{
dataAdapter.SafeMapping.Add("TZ_COLUMN", typeof(string));
dataAdapter.TableMappings.Add("Table", "Table");
OracleGlobalization glob2 = connection.GetSessionInfo();
glob2.TimeStampTZFormat = "DD-MON-YYYY HH:MI:SS.FF AM TZH:TZM";
connection.SetSessionInfo(glob2);
dataAdapter.Fill(dataSet);
}
foreach (DataRow row in dataSet.Tables[0].Rows)
{
// column is string with timezone name, I want offset
}
}
谢谢