同事遇到一個狀況,使用OleDbCommand查詢ORACLE上的Database Link時,系統回報以下錯誤:
ORA-02041: client database did not begin a transaction

Goggle了一下,發現問問題的人挺多的,但回答很分歧,沒法一下子得到正解。反覆測試後,我得到的結論如後。

當使用Oracle Database Link時,因涉及兩台以上的Oracle Server,自動啟用Distributed Transaction可以被理解(SQL Server亦是如此)。但網路上的討論似乎都集中火力在避免啟用Distributed Transaction上,而不是研究怎麼順利啟用它。Anyway,我試出兩種成功的做法。第一種是用ORACLE提供的OLEDB,關鍵是要將Registry中的HKLM\SOFTWARE\ORACLE\OLEDB\DistribTX由1改為0,表示停用分散式交易(我懷疑這會導致所有的Oracle OLEDB操作都失去分散式交易的能力,值得留意)。程式碼如下:

   1:  static void testOraOle()
   2:  {
   3:      OleDbConnection cn =
   4:          new OleDbConnection(
   5:          "Provider=OraOLEDB.Oracle; Data Source=Ora1; " +
   6:          "User Id=blah; Password=blahblah;");
   7:      cn.Open();
   8:      OleDbCommand cmd = 
   9:          new OleDbCommand("select * from myTable@Ora2", cn);
  10:      OleDbDataReader dr = cmd.ExecuteReader();
  11:      while (dr.Read())
  12:          Console.WriteLine(dr[0].ToString());
  13:      dr.Close();
  14:      cn.Close();
  15:  }

使用ODP.NET時,關鍵則在Connection String中要加上Enlist=false停用分散式交易,如下:

   1:  static void testOraODP()
   2:  {
   3:      //程式碼要宣告using ODP = Oracle.DataAccess.Client;
   4:      ODP.OracleConnection cn = 
   5:          new ODP.OracleConnection(
   6:          "Data Source=Ora1; User Id=blah; Password=blahblah; " +
   7:          "Enlist=false;");
   8:      cn.Open();
   9:      ODP.OracleCommand cmd = 
  10:          new ODP.OracleCommand("select * from myTable@Ora2", cn);
  11:      ODP.OracleDataReader dr = cmd.ExecuteReader();
  12:      while (dr.Read())
  13:          Console.WriteLine(dr[0].ToString());
  14:      dr.Close();
  15:      cn.Close();
  16:  }

至於System.Data.OracleClient,在我的測試中,即使加上Enlist=false仍會傳回相同錯誤,是否註定無法支援或仍有其他的解法,暫時不得而知,若有人有成功案例再反應給我吧!


Comments

# by 路人甲

ADO 連線字串加上 DistribTX=0 或 ODBC 就要設置 MTS=T

Post a comment