2012-12-19 18 views
5

Từ C#, sử dụng odp.net, tôi gọi hàm oracle trả về một con trỏ. Một số cột có loại "dấu thời gian với múi giờ" (TSTZ). Nếu tôi trực tiếp sử dụng OracleDataAdapter, các cột đó sẽ được chuyển thành System.DateTime và thông tin múi giờ bị mất. Đây là hành vi và đề nghị có vẻ là để sử dụng SafeMapping để buộc chuyển đổi sang chuỗi như:oracle odp.net Chuyển đổi SafeMapping nếu dấu thời gian với múi giờ - cách lấy bù trừ thay vì tên vùng

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

sau đó tôi thực sự có được TSTZ như là một chuỗi, nhưng nó sử dụng định dạng DD-MON-YYYY HH:MI:SS.FF AM TZR như thế này:

23-NOV-12 08.10.12.057868000 PM ASIA/CALCUTTA 

những gì tôi muốn nó thay vì bù đắp (ví dụ như định dạng như DD-MON-YYYY HH:MI:SS.FF AM TZH:TZD như:

23-NOV-12 08.10.12.057868000 PM +04:30 

Khi tôi truy vấn oracle trực tiếp (nói trong S ql Developer), tôi có thể sử dụng

Alter Session Set Nls_Timestamp_Tz_Format='DD-MON-YYYY HH:MI:SS.FF AM TZH:TZM' 

để lấy định dạng tôi muốn. Sử dụng odp.net tôi đã cố gắng cả hai thiết lập định dạng trong SetSessionInfo:

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

cũng như thực hiện các alter session lệnh bằng cách sử dụng kết nối tương tự, nhưng không có bất kỳ tác dụng. Tôi cho rằng điều này là do việc chuyển đổi thành chuỗi diễn ra ở giai đoạn sau và cài đặt kết nối không có hiệu lực.

Có cách nào khác để có odp.net cung cấp cho tôi khoản bù trừ trực tiếp không? Tôi không thể thay đổi hàm oracle db, vì vậy việc sử dụng ví dụ tz_offset trong phương thức này không phải là một tùy chọn.

Nếu điều này là không thể, cách tốt nhất để chuyển đổi chuỗi múi giờ thành offset là gì? tôi đang nghĩ đến việc thực hiện một

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

một lần để xây dựng một lookup table, nhưng sẽ rất vui nếu có bất kỳ lựa chọn tốt hơn.

mã truy Dữ liệu của tôi, kể cả những điều tôi đã cố gắng:

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

Cảm ơn

+0

Loại bỏ hoàn toàn thông tin múi giờ có vẻ giống như lỗi hơn là hành vi mong đợi đối với tôi. Vì tôi không quen với OPD.NET sau đây là một đoán nhưng bạn có thể có thể bọc các cuộc gọi chức năng trong một thủ tục lưu trữ mà chuyển tiếp cuộc gọi đến chức năng ban đầu. Trình bao bọc (để nó chạy trên cơ sở dữ liệu trước khi chuyển đổi kiểu) có thể trích xuất múi giờ và báo cáo nó trở lại làm cột bổ sung. –

+0

Cảm ơn, nhưng tôi không thể thay đổi phương pháp này. Tuy nhiên, tôi chỉ tìm ra một cách rất đơn giản để làm cho DataAdapter trả về các kiểu oracle cụ thể. –

Trả lời

2

Trông giống như một giải pháp rất đơn giản là để thiết lập

dataAdapter.ReturnProviderSpecificTypes = true; 

Điều này dường như làm cho ODP.net không thực hiện converstion lossy net System.DateTime nhưng thay vì sử dụng nó datetypes riêng của.

1

Có lẽ vào liên kết sau đây có thể giúp đỡ?

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

này kể về OracleTimeStampTZ loại mà có thể lưu trữ các thông tin múi giờ cũng có. Thuộc tính múi giờ trả về thông tin về múi giờ.

+0

Cảm ơn. Vấn đề là tôi không biết cách làm cho ODP.net trả về thay vì DateTime (mặc định) hoặc chuỗi/byte [] (sử dụng tính năng safemapping) –