CRecordSet, CDatabase dynamisch ?



  • So, bevor ich noch wahnsinnig werde und meinen Laptop aus dem Fenster werfe, hier
    der letzte Versuch. Problemstellung wie oben angedeutet; ich möchte diverse
    Recordsets ( die an sich alle perfekt funktionieren ) über eine allgemeine
    CRecordSetklasse abfackeln; dies scheint bei weitem nicht so einfach zu sein, wie ich mir das wohl etwas blauäugig gedacht habe. Orientiert habe ich mich an den spärlichen Microsoft Beispielen dynabind, catalog etc. - funktioniert aber trotzdem nicht.
    Gedacht habe ich mir das folgendermaßen, in der Open Funktion von CRecordSet baue ich mir eine verkettete Liste mit den einzelnen Spalten auf. Diese Informationen hole ich mir über CColumns ( wie in dynabind ) - das funktioniert ausnahmsweise perfekt.
    Eigentlich ( dachte ich zumindest ) brauche ich doch dann nur in DoFieldExchange über die einzelen Elemente aus meiner verketteten Liste zu gehen und je nach Typ die einzelnen RFX_Text etc. aufrufen. Und ab jetzt geht aber praktisch gar nichts mehr; egal was ich mache, irgendwann stürzt die Funktion hier immer ab, entweder bei m_nOperation==::AllocCache oder m_nOperation==::BindFieldToColumn. Das Problem scheint irgendwie zu sein, daß die MFC im Hintergrund mit ihren eigenen Buffern arbeitet, die logischerweise gar nicht angelegt sind. Wo liegt
    hier mein Denkfehler ?

    Nachfolgend noch die wahrscheinlichen Fehlerquellen,
    bin für jeden Tip dankbar

    void CKontoRecordSet::Move (long lRows, WORD nType) 
    {
    
    	CColumns Spalten;
    	int      nSpalten = 0;
    
    	if ( !m_ISFieldsLoaded )
    	{
    
    	   Spalten.m_pDatabase = m_pDatabase;
    
    	   Spalten.m_strTableNameParam = "KONTEN";
    
    	   Spalten.Open ();
    
    	   while ( !Spalten.IsEOF() )
    		{
    
    			//
    
    			nSpalten++;
    
    			CMyODBCFieldInfo *pCMyODBCFieldInfo = new  MyODBCFieldInfo;
    
    	                pCMyODBCFieldInfo->Name = Spalten.m_strColumnName;
    
    			pCMyODBCFieldInfo->nSQLType = Spalten.m_nDataType;
    
    			pCMyODBCFieldInfo->nPrecision = Spalten.m_lPrecision;
    
    			pCMyODBCFieldInfo->nScale = Spalten.m_nScale;
    
    		        pCMyODBCFieldInfo->ISNullable = Spalten.m_nNullable;
    
    			pCMyODBCFieldInfo->pValueCStr = 0;
    
    			pCMyODBCFieldInfo->pValueCOleDateTime = 0;
    
    			switch ( pCMyODBCFieldInfo->nSQLType )
    			{
    
    				case SQL_CHAR :					 
    				case SQL_VARCHAR :
    				case SQL_NUMERIC :
    				case SQL_DECIMAL :		 
    				case SQL_DOUBLE :
    				case SQL_INTEGER :
    				case SQL_BINARY :
    				case SQL_VARBINARY :
    				case SQL_LONGVARBINARY :
    				case SQL_SMALLINT :
    				case SQL_FLOAT :
    				case SQL_REAL :
    				case SQL_TINYINT :
    				case SQL_BIT :
    				case SQL_GUID :					
    				case SQL_BIGINT:
    				case SQL_DATE :			   
    				case SQL_TIME :				 
    				case SQL_LONGVARCHAR :
    
    					  pCMyODBCFieldInfo->pValueCStr = new CString ('\x00', pCMyODBCFieldInfo->nPrecision + 1);
    					  break;
    
    				case SQL_TIMESTAMP :
    
    					  pCMyODBCFieldInfo->pValueCOleDateTime = new COleDateTime;
    					  break;
    
    			}
    
    			m_ListeFields.AddTail (pCMyODBCFieldInfo);
    
    			//
    
    		   Spalten.MoveNext ();
    
    		}
    
    	   Spalten.Close ();
    
    	   m_nFields = nSpalten;
    
    	   m_ISFieldsLoaded = TRUE;
    
    	}
    
    	CRecordset::Move (lRows, nType);
    
    }
    
    void CKontoRecordSet::DoFieldExchange (CFieldExchange *pFX)
    {
    
    	CMyODBCFieldInfo *pCMyODBCFieldInfo;
    	POSITION         Pos;
    
    	pFX->SetFieldType (CFieldExchange::outputColumn);
    
       for ( Pos = m_ListeFields.GetHeadPosition (); Pos; )
    	{
    
    		 pCMyODBCFieldInfo = (CMyODBCFieldInfo *) m_ListeFields.GetNext (Pos);
    
    		 switch ( pCMyODBCFieldInfo->nSQLType )
    		 {
    
              case SQL_CHAR :					 
              case SQL_VARCHAR :
    			 case SQL_NUMERIC :
    	       case SQL_DECIMAL :
    			 case SQL_BINARY :
    			 case SQL_VARBINARY :
    			 case SQL_LONGVARBINARY :
    			 case SQL_SMALLINT :
    			 case SQL_FLOAT :
    			 case SQL_REAL :
    			 case SQL_TINYINT :
    			 case SQL_BIT :
    			 case SQL_GUID :					
    	       case SQL_BIGINT:
    			 case SQL_DATE :			   
    			 case SQL_TIME :				 
    			 case SQL_LONGVARCHAR :
    
    				   RFX_Text (pFX, pCMyODBCFieldInfo->Name.GetBuffer (1), *(pCMyODBCFieldInfo->pValueCStr));
    					break;
    
    			 case SQL_TIMESTAMP :
    
    				   RFX_Date (pFX, pCMyODBCFieldInfo->Name.GetBuffer (1), *(pCMyODBCFieldInfo->pValueCOleDateTime));
    					break;
    
    		 }
    
    	}
    
    }
    


  • ich hab das mal so gemacht:

    void CDepot::ImplementColumns()
    {
    //Öffnet aktuelle Datenbank mit anderen Spalten
    	extern View* View_Handle;
    	if (View_Handle != NULL && View_Handle->Table_Name.GetSize() > 0)
    	{
    		if (!View_Handle->Table_Name[View_Handle->step_run + 1].IsEmpty())
    		{
    			int lauf = 0;
    			//übergibt Zeiger auf CColumns-Objekt und bindet Datenbank an
    			m_act_db.Open(NULL, FALSE, FALSE, (_T("ODBC;DSN=Database")), TRUE);
    			CColumns* m_DB_Col_end = new CColumns(&m_act_db); 
    			m_DB_Col_end->m_strTableNameParam = View_Handle->Table_Name[View_Handle->step_run + 1];
    			m_DB_Col_end->Open(CRecordset::snapshot);
    			m_DB_Col_end->MoveFirst();
    			//überträgt Spaltennamen in CArray-Objekt
    			while (!m_DB_Col_end->IsEOF())
    			{
    				m_actCol_end.Add(m_DB_Col_end->m_strColumnName);
    				m_actCol_end[lauf].Insert(0, '[');			//für Verarbeitung der SQL-Befehle
    				m_actCol_end[lauf].Insert(m_actCol_end[lauf].GetLength(), ']');
    				m_typCol_end.Add(m_DB_Col_end->m_strTypeName);
    				m_DB_Col_end->MoveNext();
    				lauf++;
    			}
    			BuildValueLists();
    			//SaveArrayToFile();
    			delete m_DB_Col_end;
    		}
    	}
    }
    
    void CDepot::BuildValueLists()
    {
    	size = m_actCol_end.GetSize();
    	int lauf2 = 0;
    	int lauf = 0;
    	while (lauf2 < size)
    	{ 
    		m_dblCol_end.Add(lauf);
    		lauf++;
    		lauf2++;
    	}
    }
    

    so hats bei mir geklappt, über die diversen arrays kannst du dann die spalten und werte ansprechen.
    table_name sind die entsprechenden tabellennamen.


Anmelden zum Antworten