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
-
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 dankbarDas 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