ODP.NET 無法顯示 raise_application_error 自訂訊息
| | | 0 | |
接獲報案,某 Oracle Package 使用 raise_application_error 抛回自訂錯誤代碼與錯誤訊息(其中包含輸入參數以利偵錯),使用 ODP.NET 呼叫時理應可在 Exception.Message 看到自訂錯誤訊息,但某支程式出錯時卻只傳回錯誤代碼並抱怨找不到該代碼對應訊息:ORA-20001: Message 20001 not found; product=RDBMS; facility=ORA
經過調查與對照測試,發現與程式被包在 TransactionScope 有關。用以下程式重現與驗證問題:
using Oracle.DataAccess.Client; using System; using System.Collections.Generic; using System.Data.SqlClient; using System.Linq; using System.Text; using System.Transactions; namespace OraExpLab { class Program { static string csOra = "Data Source=...;User ID=...;Password=....";
static string csSql = "Data Source=(local);Integrated Security=SSPI;";
static void querySqlServer()
{ using (var cn = new SqlConnection(
csSql + "Application Name=" + Guid.NewGuid().ToString())) { var cmd = new SqlCommand("SELECT getdate() as D", cn);
cn.Open();
var dr = cmd.ExecuteReader();
dr.Read();
Console.WriteLine(dr["D"]); cn.Close();
}
}
static void queryOraServer()
{ using (OracleConnection cn = new OracleConnection(csOra))
{ cn.Open();
var cmd = cn.CreateCommand();
cmd.CommandText = "SELECT SYSDATE as D FROM DUAL"; var dr = cmd.ExecuteReader();
dr.Read();
Console.WriteLine(dr["D"]); cn.Close();
}
}
static void raiseOraError()
{ using (OracleConnection cn = new OracleConnection(csOra))
{ cn.Open();
var cmd = cn.CreateCommand();
cmd.CommandText = @" declare
begin
raise_application_error(-20001, '我錯了');
end;
";
try { cmd.ExecuteNonQuery();
}
catch (Exception ex) { Console.WriteLine("ORACLE CUST ERROR:" + ex.Message); }
}
}
static void Main(string[] args)
{ raiseOraError();
using (var tx = new TransactionScope())
{ querySqlServer();
queryOraServer();
raiseOraError();
Console.WriteLine(
Transaction.Current.TransactionInformation.LocalIdentifier);
Console.WriteLine(
Transaction.Current.TransactionInformation.DistributedIdentifier);
}
Console.Read();
}
}
}
用一小段 PL/SQL Script 故意抛回自訂錯誤,單獨呼叫時可由 ex.Message 看到自訂訊息「我錯了」。隨後用 TransactionScope 將其與 SQL 查詢包起來,刻意觸發分散式交易,並由 Transaction.Current.TransactionInformation.DistributedIdentifier 驗證分散式交易已啟動(參考),第二次呼叫傳回錯誤訊息變成 ORA-20001: Message 20001 not found; product=RDBMS; facility=ORA。
執行結果如下:
ORACLE CUST ERROR:ORA-20001: 我錯了
ORA-06512: 在 line 4
2017/3/28 上午 05:40:59
2017/3/28 上午 05:41:00
ORACLE CUST ERROR:ORA-20001: Message 20001 not found; product=RDBMS; facility=ORA
d9f57da1-9ad4-4623-b91c-7ac4044fc7c1:1
e01b29b2-888a-4e8c-b612-452a22e357fc
進一步對照測試,發現這現象只發生在使用 Unmanaged ODP.NET,使用 Managed ODP.NET 不管有無分散式交易都可看到自訂錯誤訊息。猜想這與 Oracle Client 的 Unmanaged 程式庫行為有關,現階段遇此困擾,可考慮改用 Managed ODP.NET 逃避問題。
Comments
Be the first to post a comment