6

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
    }
    }

ありがとう

4

2 に答える 2

2

非常に簡単な解決策は設定することのように見えます

dataAdapter.ReturnProviderSpecificTypes = true;

これにより、ODP.netは.net System.DateTimeへの不可逆変換を実行せず、代わりに独自の日付タイプを使用するようになります。

于 2013-01-03T13:55:02.170 に答える
1

おそらく、次のリンクが役立ちますか?

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

これは、タイムゾーン情報も格納できるOracleTimeStampTZタイプについて説明しています。timezoneプロパティは、タイムゾーンに関する情報を返します。

于 2012-12-27T03:50:24.580 に答える