2017-02-16 6 views
0

우리는 asp.net mvc를 웹 애플리케이션으로 사용하고 오라클 12C를 데이터베이스로 사용하고 Oracle.DataAccess.Client (12.1.0, 64 비트 버전)를 사용하여 연결합니다. Oracle Database 및 asp.net MVC 애플리케이션은 64 비트 시스템에서도 실행됩니다.오라클 스토어드 프로 시저 리턴 커서가 TOAD에서 빠름 C#으로 천천히 복귀

저장 프로 시저 중 하나가 출력 매개 변수로 커서를 반환합니다.

이제 우리는 TOAD 또는 SQL Developer에서 동일한 저장 프로 시저를 실행하는 데 1 초도 채 걸리지 않지만 C#이 동일한 저장 프로 시저를 실행하면 약 35 초가 소요됩니다. !!! 돌아 가기. TOAD, SQL Developer 및 asp.net iis 서버는 모두 내 로컬 시스템에 있고 Oracle 서버는 다른 시스템에 있습니다.

C#에서는 연결을 여는 데 걸린 시간과 C#에서 저장 프로 시저를 호출하는 시간, 완료 및 반환 시간, DataSet을 변환하는 데 걸린 시간 등 모든 종류의 시간을 기록했습니다. C# 목록. 모든 타이밍을 관찰 한 후 우리는 그런 경우도 같은 시간이 소요됩니다 두꺼비와 SQL 개발자, 그래서 네트워크는 문제가되지 않는 경우 문을 다음은, 우리가 네트워크 문제가 될 수 있다고 생각 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; 

걸리는 것을 알 수있다.

우리가 시도한 것 : 유일한 용의자는 ODP.NET 드라이버이므로 모든 oracle 클라이언트가 제거되고 다시 설치됩니다. 사용하지 마십시오.

이제 sqlnet.ora 또는 tns 파일 연결에서 구성해야하는 것이 있는지 확인하려고합니까? 그러나 어떤을 찾을 수 없습니다 ... 여기

는 전체 코드

입니다

공공 DataTable을 GetDataTable (문자열 psStoredProcedure) { LogInfo (psStoredProcedure); 누군가가 그것을 밖으로 시도 할 수 있습니다 같은 상황에 직면하는 경우 나이를 위해

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

는 대답이 될 수 있습니다 다음

 //****************************************************************** 
     //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이다.

며칠을 조사한 후 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;}