2012-12-19 60 views
5

Z C#, używając odp.net, nazywam funkcję oracle, która zwraca kursor. Niektóre kolumny są typu "znacznik czasu ze strefą czasową" (TSTZ). Jeśli użyję bezpośrednio OracleDataAdapter, te kolumny zostaną przekonwertowane na System.DateTime, a informacje o strefie czasowej zostaną utracone. Jest to normalne zachowanie i zalecenie wydaje się być użycie SafeMapping wymusić konwersję do łańcucha jak:oracle odp.net Konwersja SafeMapping jeśli sygnatura czasowa z timezone - jak uzyskać offset zamiast nazwy strefy

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

I wtedy rzeczywiście uzyskać TSTZ jako ciąg, ale jest w formacie DD-MON-YYYY HH:MI:SS.FF AM TZR tak:

23-NOV-12 08.10.12.057868000 PM ASIA/CALCUTTA 

Co chcę zamiast offsetu (np formatu jak DD-MON-YYYY HH:MI:SS.FF AM TZH:TZD jak:

23-NOV-12 08.10.12.057868000 PM +04:30 

Podczas kwerendy oracle bezpośrednio (powiedzmy w S ql Developer), mogę użyć formatu . Korzystanie odp.net Próbowałem zarówno ustawiania formatu w SetSessionInfo:

connection.Open(); 
OracleGlobalization glob = connection.GetSessionInfo(); 
glob.TimeStampTZFormat = "DD-MON-YYYY HH:MI:SS.FF AM TZH:TZM"; 
connection.SetSessionInfo(glob); 

jak również wykonaniem polecenia alter session przy użyciu tego samego połączenia, ale nie ma żadnego wpływu. Zakładam, że dzieje się tak dlatego, że konwersja na ciąg ma miejsce na późniejszym etapie, a ustawienia połączenia nie działają.

Czy istnieje inny sposób na to, aby odp.net dostarczył mi odsyłkę bezpośrednio? Nie mogę zmienić funkcji db Oracle, więc używanie na przykład tz_offset w metodzie nie jest opcją.

Jeśli nie jest to możliwe, jaki jest najlepszy sposób przekonwertowania ciągu strefy czasowej na przesunięcie? Jestem obecnie na myśli wykonywanie

select TZNAME, TZABBREV, tz_offset(TZNAME) as TZOFFSET 
from V$TIMEZONE_NAMES 

raz zbudować tablicowanie, ale byłby szczęśliwy, jeśli są jakieś lepsze opcje.

Mój kod pobierania danych, w tym rzeczy, próbowałem:

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

Dzięki

+0

Niejawne odrzucanie informacji o strefie czasowej brzmi raczej jak błąd niż oczekiwane zachowanie. Ponieważ nie jestem obeznany z OPD.NET to domysły, ale prawdopodobnie można zawinąć wywołanie funkcji w innej procedurze przechowywanej, która przekazuje wywołanie do oryginalnej funkcji. Opakowanie (do uruchamiania w bazie danych przed konwersją typu) może wyodrębnić strefę czasową i zgłosić ją z powrotem jako dodatkową kolumnę. –

+0

Dzięki, ale niestety nie mogę zmienić metody. Jednak właśnie zorientowałem się, co wygląda na bardzo prosty sposób, aby DataAdapter zwracał specyficzne typy oracle. –

Odpowiedz

2

Wygląda to bardzo proste rozwiązanie jest ustawienie

dataAdapter.ReturnProviderSpecificTypes = true; 

Wydaje się, aby nie wykonywać ODP.net stratnej converstion do .NET System.DateTime ale zamiast wykorzystać swój własny typach danych.

1

Może Poniższy link może pomóc?

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

Informuje o rodzaju OracleTimeStampTZ który może przechowywać informacje strefy czasowej również. Właściwość strefy czasowej zwraca informacje o strefie czasowej.

+0

Dzięki. Problem polegał na tym, że nie wiedziałem, jak sprawić, by ODP.net zwrócił to zamiast DateTime (domyślnie) lub string/byte [] (używając funkcji bezpieczeństwa) –