2017-02-16 57 views
0

我們使用asp.net mvc作爲Web應用程序並將oracle 12C用作數據庫'Oracle.DataAccess.Client'(12.1.0,64位版本)用於連接到Oracle數據庫以及我們的asp.net MVC應用程序也在64位機器上運行。Oracle存儲過程將光標放慢到C#,在TOAD上快速執行

我們的一個存儲過程返回一個光標作爲輸出參數。

現在,當我們在TOAD或SQL Developer上執行它時,相同的存儲過程只需要不到一秒的時間,但是當C#執行相同的存儲過程時,大約需要35秒。返回。 TOAD,SQL Developer和asp.net iis服務器都在我的本地機器上,Oracle服務器位於不同的機器上。

在C#中,我記錄了各種時間,比如打開連接需要多長時間,C#調用存儲過程的時間戳以及它完成和返回的時間,轉換DataSet需要多長時間到C#列表。觀察所有的時間之後,我們發現下面的語句需要35秒

  OracleDataAdapter loDataAdapter = new OracleDataAdapter(loCommand); 
      LogInfo("fill DataTable");//logs time stamp saying start 
      loDataAdapter.Fill(loDataTable); 
      LogInfo("fill DataTable",false);//logs time stamp saying Done 
      loDataAdapter = null; 

我們認爲這可能是網絡的問題,如果是這樣的蟾蜍和SQL開發人員也應該採取相同的時間的情況下,這樣的網絡是不是一個問題。

我們試過了: 我唯一的懷疑是ODP.NET驅動程序,所以刪除了所有的Oracle客戶端並重新安裝它們,沒用。

現在試圖查看是否有一些事情我必須在sqlnet.ora或tns文件連接上進行配置?但找不到任何...

下面是完整的代碼

公衆的DataTable GetDataTable(字符串psStoredProcedure) { LOGINFO(psStoredProcedure);

 //****************************************************************** 
     //Function.........GetDataTable 
     //Description......Gets a data set (with the schema) from stored procedure 
     //Input Param......(1)Stored procedure name 
     //     (2)Boolean to determine if we want to get the schema 
     //Output...........Return DataTable 
     // 
     //****************************************************************** 

     OracleCommand loCommand = new OracleCommand(); 
     OracleConnection loConnection = new OracleConnection(msConnectionString); 
     DataTable loDataTable = new DataTable(); 

     //---Main Execution Block 
     try 
     { 
      if (!(loConnection.State == ConnectionState.Open)) 
      { 
       LogInfo("Open Conn"); 
       loConnection.Open(); 
       LogInfo("Open Conn",false); 
      } 

      //---Define the SelectCommand 
      if (moCommand == null) 
      { 
       loCommand = new OracleCommand(); 
      } 
      else 
      { 
       loCommand = moCommand; 
       moCommand = null; 
      } 

      loCommand.CommandText = psStoredProcedure; 
      loCommand.Connection = loConnection; 
      loCommand.CommandType = CommandType.StoredProcedure; 

      //---Populate the dataset 
      OracleDataAdapter loDataAdapter = new OracleDataAdapter(loCommand); 
      LogInfo("fill DataTable"); 
      loDataAdapter.Fill(loDataTable); 
      LogInfo("fill DataTable",false); 
      loDataAdapter = null; 
     } 
     catch (Exception oExcep) 
     { 
      throw oExcep; 
     } 
     finally 
     { 
      //---Close the connection 
      if (loConnection.State == ConnectionState.Open) 
      { 
       LogInfo("Close"); 
       loConnection.Close(); 
       LogInfo("Close", false); 
      } 

      loCommand = null; 
      loConnection = null; 
     } 
     LogInfo(psStoredProcedure, false); 
     return loDataTable;} 

以下是PL/SQL存儲過程:

CREATE OR REPLACE PROCEDURE REF_LIST_INQ ( 
ivID   IN VARCHAR2 DEFAULT NULL,   
ivAID   IN VARCHAR2 DEFAULT NULL, 
ivDID   IN VARCHAR2 DEFAULT NULL, 
ivSelection  IN VARCHAR2 DEFAULT NULL, 
ivStartDate  IN VARCHAR2 DEFAULT NULL, 
ivEndDate   IN VARCHAR2 DEFAULT NULL,  
ocRefList  OUT ES_PACKAGE.cursorType, 
ovReturnCode  OUT VARCHAR2, 
ovErrorMsg   OUT VARCHAR2 
) 
AS 

cmdSQL  VARCHAR2(4000) := NULL; 
whereCause VARCHAR2(2000) := NULL; 
selectCause VARCHAR2(2000) := NULL; 


BEGIN 
    /************ 
--Hundreds of lines of PL/SQL Code for 
    -- dynamically creating sql statements 
    -- and assigning it to 'selectCause' and 'whereCause' 
*************************/ 

    cmdSQL := selectCause || whereCause || ' ORDER BY SD.MODIFIED_DATE DESC, SD.REFERRAL_NUMBER'; 

    OPEN ocRefList FOR cmdSQL; 
    ovReturnCode := '0'; 

    EXCEPTION WHEN OTHERS THEN 
     ovErrorMsg := 'REF_LIST_INQ - ' || SUBSTR(SQLERRM,1,200); 
     ovReturnCode := '-1'; 

END REF_LIST_INQ; 
/
+0

發佈您的plsql測試代碼以及​​ - 我猜你只是返回遊標,但沒有從中拉出所有記錄 - 這是「填充」語句正在做什麼。 –

+0

pl/sql裏存儲過程是動態創建語句並賦值給一個變量'cmdSQL'。最後,我們爲該語句打開一個遊標。 – venu

+0

像以下一樣,OPEN ocReferralList FOR cmdSQL;我將盡快在我的問題中添加pl/sql。 – venu

回答

0

對我來說這是一個答案,可能是如果有人正面臨着同樣的情況可以嘗試一下。

經過幾天的研究,下面的C#語句幫助了我。

loCommand.FetchSize = loCommand.FetchSize * 18192; 

按我的理解(我不擅長描述,盡我的水平最好)這僅適用於64位版本,如果我們沒有指定「FETCHSIZE」,它會繼續獲取預定義的大小(我相信128k)的數據來自在Oracle DB上打開的遊標,它將執行往返行程,直到遊標提供的數據完成。

所以這裏是完整的C#代碼,但是一行代碼有很大的不同。

//****************************************************************** 
    //Function.........GetDataTable 
    //Description......Gets a data set (with the schema) from stored procedure 
    //Input Param......(1)Stored procedure name 
    //     (2)Boolean to determine if we want to get the schema 
    //Output...........Return DataTable 
    // 
    //****************************************************************** 

    OracleCommand loCommand = new OracleCommand(); 
    OracleConnection loConnection = new OracleConnection(msConnectionString); 
    DataTable loDataTable = new DataTable(); 

    //---Main Execution Block 
    try 
    { 
     if (!(loConnection.State == ConnectionState.Open)) 
     { 
      LogInfo("Open Conn"); 
      loConnection.Open(); 
      LogInfo("Open Conn",false); 
     } 

     //---Define the SelectCommand 
     if (moCommand == null) 
     { 
      loCommand = new OracleCommand(); 
     } 
     else 
     { 
      loCommand = moCommand; 
      moCommand = null; 
     } 

     loCommand.CommandText = psStoredProcedure; 
     loCommand.Connection = loConnection; 
     loCommand.CommandType = CommandType.StoredProcedure; 
//Here is the Hero 
loCommand.FetchSize = loCommand.FetchSize * 18192; 

     //---Populate the dataset 
     OracleDataAdapter loDataAdapter = new OracleDataAdapter(loCommand); 
     LogInfo("fill DataTable"); 
     loDataAdapter.Fill(loDataTable); 
     LogInfo("fill DataTable",false); 
     loDataAdapter = null; 
    } 
    catch (Exception oExcep) 
    { 
     throw oExcep; 
    } 
    finally 
    { 
     //---Close the connection 
     if (loConnection.State == ConnectionState.Open) 
     { 
      LogInfo("Close"); 
      loConnection.Close(); 
      LogInfo("Close", false); 
     } 

     loCommand = null; 
     loConnection = null; 
    } 
    LogInfo(psStoredProcedure, false); 
    return loDataTable;}