MS-SQL-Stored Procedure: RecordSet löscht/verdeckt Output-Parameter



  • Hallo,

    ich rufe über ADO eine gespeicherte Prozedur auf und eigentlich funktioniert das auch ganz gut, so lange ich das zurückgegebene DataSet nicht weiter behandle.

    Mit

    m_Cmd->Execute(NULL,NULL,ADODB::adCmdStoredProc);
    

    führe ich die gespeicherte Prozedur aus - ohne das zurückgegebene DataSet abzufangen.

    In vVariable wird der dann der Output-Wert aus der Prozedur gespeichert, so wie es sein soll:

    VARIANT vVariable;
    vVariable.vt = VT_BSTR; 
    vVariable = m_Cmd->Parameters->GetItem("@OutputParameterName")->Value;
    

    Da ich aber auch die zurückgelieferten Datensätze bearbeiten muss, fülle ich diese Datensätze in ein ADODB::Recordset.
    Dazu hänge ich vor den obigen Execute-Befehl den Namen meines ADODB::Recordset's (meinRecordSet):

    meinRecordSet = m_Cmd->Execute(NULL,NULL,ADODB::adCmdStoredProc);
    

    Die Datensätze sind jetzt auch in meinRecordSet gespeichert und ich kann sie problemlos abarbeiten.
    Wenn ich allerdings jetzt (nach dem geänderten Execute-Befehl) auf die vVariable zugreife, ist der Wert "Empty"?

    An der gespeicherten Prozedur kann es nicht liegen, da lt. SQL-Profiler-Tool, die Output-Werte vom SQL-Server zurückgegeben wurden.
    Ich vermute, dass die Output-Parameter-Werte irgendwo mit in den RecordSet "gefüllt" wurden und jetzt im Nirvana gelandet sind...

    Weiss jemand von Euch, wie ich an die Output-Werte komme?

    cu
    Chris


  • Mod

    Zeig mal etwas mehr Code. Evtl. gehst Du mit den COM Variablen falsch um.

    BTW: Alleine der nachfolgende Code ist definitv falsch. Er erzeugt ein Leak. Der BSTR wird nie freigegeben. Wenn Du es nicht noch selbst behandelst.

    VARIANT vVariable;
    vVariable.vt = VT_BSTR; 
    vVariable = m_Cmd->Parameters->GetItem("@OutputParameterName")->Value;
    

    Warum verwendest Du nicht die smarten Variant Typen



  • Erstmal Danke für Deine Antwort!

    Ich programmiere leider erst seit 3 Wochen C++ und bin im Umgang mit dynamischer Speicherreservierung noch nicht so vertraut.
    Gut möglich, dass da das ein oder andere Speicherleck noch drin ist. Ich bin für jede Hilfe dankbar 🙂

    Das ist also der komplette Code (ungeschönt).

    Aufgabe dieser Methode:
    Ich möchte eine zentrale Schnittstelle schreiben, von der ich eine Verbindung zum SQL-Server aufbaue, um dann von überall im Programm nur noch die notwendigsten Daten übergeben zu müssen.
    Es werden über eine Struktur, durch eine dynamischen Liste, die Anzahl der Parameter, Input- oder Output-Typ, Datentyp und Wert übergeben.
    Nach dem Execute-Befehl werden die Output-Werte wieder zurück in die dynamische Liste geschrieben.
    Die Datensätze werden in einem RecordSet gespeichert, das ebenfalls im Methodenaufruf übereben wird.

    bool SQLMngr::execStoredProcedure(SqlProzedur &meineSqlProzedur)
    {
    
    	 USES_CONVERSION;
    	 VARIANT vVariable;
    
    	 //Variablen-Deklaration
     	 CWaitCursor wait;
    	 bool bSuccess = true;
    	 bool bVersion = false;
    
       try
       {
    	  //besteht keine Verbindung zur DB
          if(m_Conn == 0)
          {
    		 //Verbindung aufbauen
             m_Conn = ADODB::_ConnectionPtr(__uuidof(ADODB::Connection));
             m_Conn->ConnectionTimeout = 6; //Zeitangabe in Sekunden
             m_Conn->Open(getConnstr(),"","",ADODB::adConnectUnspecified);				
         }
    
         //Recordset öffnen
         m_Cmd.CreateInstance(__uuidof(ADODB::Command));
    	 meineSqlProzedur.myRecordSet.CreateInstance(__uuidof(ADODB::Recordset));
         m_Cmd->ActiveConnection = m_Conn;
    
    		 //Stored Procedure festlegen
    		 m_Cmd->CommandType      = ADODB::adCmdStoredProc;
    		 m_Cmd->CommandText      = _bstr_t(meineSqlProzedur.prozedurname);
    
    			 //zusammenbauen der Parameter für die StoredProc 
    			 for(int i = 0; i < meineSqlProzedur.paramSqlAnzahl; i++)
    			 {
    				 //Richtung festlegen
    				 ADODB::ParameterDirectionEnum paramRichtung;
    				 paramRichtung = (meineSqlProzedur.myParams[i].parameterRichtung == false) ? ADODB::adParamOutput : ADODB::adParamInput;
    
    				 //Datentyp festlegen
    				 ADODB::DataTypeEnum paramDatentyp;
    				 if(meineSqlProzedur.myParams[i].parameterDatentyp == false)
    				 {
    					 //Ganzzahl
    					 paramDatentyp = ADODB::adInteger;
     					 vVariable.vt  = VT_INT;
    				 }
    				 else
    				 {
    					 //Zeichenkette
    					 paramDatentyp = ADODB::adVarChar;
     					 vVariable.vt  = VT_BSTR;
    				 }
    				 vVariable.bstrVal = _bstr_t(meineSqlProzedur.myParams[i].parameterWert); 
    				 m_Cmd->Parameters->Append(m_Cmd->CreateParameter(_bstr_t(meineSqlProzedur.myParams[i].parameterName), 
    																  paramDatentyp,
    																  paramRichtung,
    																  8000, //max. Wert für einen varchar
    																  vVariable));
    			 }
    
    		 meineSqlProzedur.myRecordSet = m_Cmd->Execute(NULL,NULL,ADODB::adCmdStoredProc);
    
    		 //Zusammenbauen der Output-Parameter zur Rückgabe an die dyn. Liste 'meineSqlProzedur' 
    		  for(int i = 0; i < meineSqlProzedur.paramSqlAnzahl; i++)
    		  {
    		    vVariable.vt = VT_BSTR; 
    			vVariable = m_Cmd->Parameters->GetItem(meineSqlProzedur.myParams[i].parameterName)->Value;
    			 meineSqlProzedur.myParams[i].parameterWert = const_cast<char*>((LPCTSTR) W2A((_bstr_t)vVariable));		 
    		  }
    		 //Zusammenbauen der Output-Parameter zur Rückgabe an die dyn. Liste 'meineSqlProzedur' <--
       }
       catch (_com_error& ce)
       {
          handle_com_error("Fehler bei Verbindung SqlServer",
             m_pApp->m_pProf->getSqlDSNName(),ce);
    
       } 
    
       return bSuccess;
    }
    

    cu
    Chris


Anmelden zum Antworten