2012-12-19 9 views
5

odp.netを使用してC#からカーソルを返すoracle関数を呼び出します。列の中には、「タイムゾーン付きタイムスタンプ」(TSTZ)の列があります。 OracleDataAdapterを直接使用すると、これらの列はSystem.DateTimeに変換され、タイムゾーン情報は失われます。これは正常な動作や勧告のような文字列に変換を強制的にSafeMappingを使用するように思われます。私は、実際に文字列としてTSTZを取得oracle odp.netタイムゾーン付きのタイムスタンプのSafeMapping変換 - ゾーン名の代わりにオフセットを取得する方法

dataAdapter.SafeMapping.Add("column_name", typeof(string)); 

が、それはこのようなフォーマット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など:私はクエリを実行したときに、Oracleに直接(Sに言う

23-NOV-12 08.10.12.057868000 PM +04:30 

ql開発者)、私は使用できる形式を取得するには

を入手することができます。 使用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 
    } 
    } 

おかげ

+0

明示的にタイムゾーン情報を破棄すると、予想される動作ではなくバグのように聞こえるようになります。私はOPDに精通していないので、NETは次のように推測されますが、元の関数に呼び出しを転送する別のストアドプロシージャで関数呼び出しをラップする可能性があります。ラッパー(型変換前にデータベース上で実行される)は、タイムゾーンを抽出し、追加の列として報告することができます。 –

+0

ありがとうございますが、残念ながら方法を変更することはできません。しかし、私は、DataAdapterがOracle固有の型を返すようにするための非常に簡単な方法のように見えました。 –

答えて

2

が見えます。

1

おそらく、次のリンクは助けることができますか?

http://docs.oracle.com/html/A96160_01/oratyp10.htm#1130922

これはまた、タイムゾーン情報を格納できるのOracleTimeStampTZタイプについて通知します。 timezoneプロパティは、タイムゾーンに関する情報を返します。非常に簡単な解決策は

dataAdapter.ReturnProviderSpecificTypes = true; 

これはODP.netは、.NETのSystem.DateTimeに非可逆converstionを行う代わりに、それ自身のdatetypesを使用しないで作るように見えるを設定することがあるよう

+0

ありがとうございます。問題は、ODP.netにDateTime(デフォルト)またはstring/byte [](代わりにセーフマップ機能を使用)の代わりにこれを返す方法を知らなかったことです –

関連する問題