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
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ę. –
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. –