C# oracle odp.net安全映射转换如果时间戳带有时区-如何获取偏移量而不是区域名称
从c#,使用odp.net调用一个返回游标的oracle函数。某些列的类型为“带时区的时间戳”(TSTZ)。如果直接使用,这些列将转换为System.DateTime,并且时区信息将丢失。这是预期的行为,建议用于强制转换为字符串:C# oracle odp.net安全映射转换如果时间戳带有时区-如何获取偏移量而不是区域名称,c#,oracle,datetime,timezone,odp.net,C#,Oracle,Datetime,Timezone,Odp.net,从c#,使用odp.net调用一个返回游标的oracle函数。某些列的类型为“带时区的时间戳”(TSTZ)。如果直接使用,这些列将转换为System.DateTime,并且时区信息将丢失。这是预期的行为,建议用于强制转换为字符串: dataAdapter.SafeMapping.Add("column_name", typeof(string)); 然后我确实将TSTZ作为字符串获取,但它使用的格式是DD-MON-YYYY HH:MI:SS.FF AM TZR,如下所示: 23-NOV-12
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-yyyyy 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_偏移量不是一个选项
如果不可能,将时区字符串转换为偏移量的最佳方法是什么?
我目前正在考虑执行一项
select TZNAME, TZABBREV, tz_offset(TZNAME) as TZOFFSET
from V$TIMEZONE_NAMES
一旦建立了一个lookuptable,但会很高兴,如果有任何更好的选择
我的数据检索代码,包括我尝试过的内容:
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
}
}
谢谢以下链接可能会有所帮助
这说明了OracleTimeStampTZ类型,它也可以存储时区信息。timezone属性返回有关时区的信息。看起来一个非常简单的解决方案是设置
dataAdapter.ReturnProviderSpecificTypes = true;
这似乎使ODP.net不执行与.net System.DateTime的有损对话,而是使用它自己的日期类型。隐式丢弃时区信息对我来说更像是一个错误,而不是预期的行为。因为我不熟悉OPD.net,下面是一个猜测,但您可能会将函数调用包装成另一个将调用转发给原始函数的存储过程。包装器(因为它在类型转换之前在数据库上运行)可以提取时区并将其作为附加列报告。谢谢,但不幸的是,我无法更改该方法。但是,我刚刚找到了一种非常简单的方法,使DataAdapter返回oracle特定类型。谢谢。问题是我不知道如何使ODP.net返回此值,而不是DateTime(默认值)或字符串/字节[](使用安全映射功能)