Datenbankanbindung ohne Doc/View



  • Hallo,

    meine Anwendung, die ich entworfen hab, ist dialogbasierend aufgebaut. Jetzt würde ich gerne eine Datenbankanbindung über ODBC zu einem SQL-Server aufbauen. Jedoch weiss ich nicht, wie das ohne die Document/Ansichtsklassen funktioniert, was brauche ich da alles für Komponente?

    ich hab schon den Header afxdb.h in die StdAfx.h aufgenommen bzw. die afxprint.rc in die Rc-Datei, dann hab ich eine Klasse mit der Basisklasse CRecordSet erstellt bzw. die Datenbank schon in der Klasse integriert.

    nachdem ich aber einen Zeiger von meiner RecordSet-Klasse erstelle und diesen versuche anzusprechen, bricht mir das Programm ab...

    weiss einer Rat?`

    Gruss,

    chullain



  • poste ma dein code... vor allem das mit dem pointer.

    esco



  • Frage: Warum arbeitest du über einen Zeiger?

    1. Idee: Der Zeiger ist NULL
    2. Idee: Das Recordset ist nicht geöffnet (nicht lachen, ist mein Standardfehler)



  • also...

    Das ist erstmal ein Aussschnitt aus meiner RecordSet-Klasse mit den drei Methoden, die, meiner Meinung nach, unter anderem verwendet werden, beim Zugriff auf die Datenbank...

    CString CDBAnbindung::GetDefaultConnect()
    {
    	return _T("ODBC;DSN=Benutzerverwaltung");
    }
    
    CString CDBAnbindung::GetDefaultSQL()
    {
    	return _T("[dbo].[Anwendung]");
    }
    
    void CDBAnbindung::DoFieldExchange(CFieldExchange* pFX)
    {
    	//{{AFX_FIELD_MAP(CDBAnbindung)
    	pFX->SetFieldType(CFieldExchange::outputColumn);
    	RFX_Long(pFX, _T("[LftID]"), m_LftID);
    	RFX_Text(pFX, _T("[Dbuser]"), m_Dbuser);
    	RFX_Text(pFX, _T("[Dbpw]"), m_Dbpw);
    	RFX_Text(pFX, _T("[Status]"), m_Status);
    	RFX_Text(pFX, _T("[AppName]"), m_AppName);
    	RFX_Text(pFX, _T("[Server]"), m_Server);
    	RFX_Text(pFX, _T("[Anwendung]"), m_Anwendung);
    	RFX_Text(pFX, _T("[Verantw]"), m_Verantw);
    	RFX_Text(pFX, _T("[VerTel]"), m_VerTel);
    	RFX_Date(pFX, _T("[Gueltvon]"), m_Gueltvon);
    	RFX_Date(pFX, _T("[Gueltbis]"), m_Gueltbis);
    	RFX_Text(pFX, _T("[Comsi]"), m_Comsi);
    	//}}AFX_FIELD_MAP
    }
    

    Dann geschieht folgendes in meinem Dialog, wo ich den Zugriff auf die Daten in meiner Datenbank plane....

    BOOL Anmeldung::OnInitDialog()
    {
    	CDialog::OnInitDialog();
    
    	CDBAnbindung m_DBAnbindung;
    	CDBAnbindung* m_pDBAnbindung;
    
    	m_pDBAnbindung->Open();             //Abbruch "Die Anweisung verweist
                                                 //auf Speicher "0ccccccccc"...
    	if (!m_pDBAnbindung->IsBOF()){
    	  m_pDBAnbindung->MoveFirst();
    	  while (!m_pDBAnbindung->IsEOF())
    	  {
    	    m_status  = "Folgende Repositories stehen zur Auswahl: ";
    	    m_status += "\r\n";
    	    m_status += "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
    	    m_status += "\r\n";
    	    m_repository.AddString(m_pDBAnbindung->m_AppName);
    	    m_status  += m_pDBAnbindung->m_AppName;
    	    m_status += "\r\n";
    	    m_pDBAnbindung->MoveNext();
    	  }
    	}
    	if (m_pDBAnbindung->IsOpen()){
    	  m_pDBAnbindung->Close();
             }
        ...
        UpdateData(FALSE);
    }
    

    So, der Abbruch geschieht schon beim Aufrufen der Methode Open()

    Der Zeiger ist auch NULL, aber er wird doch beim Aufruf der Methode Open() initialisiert, oder?

    also irgendwas mach ich da falsch...



  • Du müßtest noch ein new machen, der Zeiger zeigt nicht auf freien Speicherplatz sondern ins Nirvana. Mach es doch mit einem normalen Objekt, das ist weniger fehlerträchtig.



  • Steht in der FAQ



  • chullain schrieb:

    CDBAnbindung m_DBAnbindung;
    	CDBAnbindung* m_pDBAnbindung;
    

    also irgendwas mach ich da falsch...

    was issn das? 😮

    der fehler, liegt wie meine vorredner schon sagte beim speicher allokieren. desweiteren empfiehlt es sich einen try-catch block zu verwenden, oder wenigstens den bool auszuwerten, den die open methode zurueckgibt. ansonsten ist es nur eien frage der zeit, bis dein tool zum naechsten datensatz springen will, obwohl er die DB nich oeffnen konnte --> absturz.

    Esco



  • Esco schrieb:

    poste ma dein code... vor allem das mit dem pointer.

    esco

    estartu_de schrieb:

    Frage: Warum arbeitest du über einen Zeiger?

    1. Idee: Der Zeiger ist NULL
    2. Idee: Das Recordset ist nicht geöffnet (nicht lachen, ist mein Standardfehler)

    wir 2 sollten ne firma aufmachen, wir kennen die fehler schon, bevor er seinen code postet 😃

    Esco



  • Ist Hellsehen gut bezahlt? 😃

    Hast du mal einen schönen Text zu "Wie greife ich ordentlich abgesichert auf die Datenbank zu"?
    Danach suche ich immer noch, mein Stand ist der aus VC++ in 21 Tagen, da kein anderes Buch den DB-Zugriff beschreibt. 😞
    Ich weiß, dass ich kaum Fehlerbehandlung drin habe, noch geht es gut - aber wie würde es besser aussehen? Leider sitzen mit momentan zwei Chefs im Nacken, so dass ich nicht zum Selberforschen komme.

    Der Codeschnipsel von chullain sieht auch der nach dem Buch aus.



  • also ich mach das folgendermassen: mittels CDatabase beim programmstart ueberpruefen, ob die datenbank existent ist und geoeffnet werden kann. die einzelnen datensaetze hole ich mir mit CRecordset, wobei sich die gesamten datenbankoperationen in einem try und catch block befinden. da kannste eigentlich ned viel falsch machen und wenn de bissle kreativ mit dem catch block arbeitest, kannste es au n zweites mal versuchen oae.

    Esco



  • Das mit der Database zu Anfang klingt schon mal gut, das sollte ich mal nachziehen. 🙂

    mit try - catch muss ich wohl noch ne Runde lesen, damit stehe ich noch sehr auf Kriegsfuß. Vor allem beim Debuggen im Fehlerfall kriege ich nen Anfall, weil man damit so schlecht findet WAS genau ihm nicht gefallen hat.
    Deswegen versuche ich so weit wie möglich mit ifs zu kommen... 🙄



  • try
    	{
    		pDBTabelle->Open();
    
    		while (!pDBTabelle->IsEOF())
    
    			{	
    				// hier dein auszufuehrender code          
    				pDBTabelle->MoveNext();
    			}
    	}
    	catch (CDBException* pe)
    	{
    		AfxMessageBox(pe->m_strError);
    	}	
    
    	pDBTabelle->Close();
    	delete pDBTabelle;
    	pDBTabelle = 0;
    

    zumindest bei oracle sind die fehler durchnummeriert. du kannst also m_strError nach seinem index (oder auch nach deinem fehlertext) durchsuchen und so schauen, ob es einer der fehler ist, den du evtl erwartet hast.

    an einer stelle kann man in meiner anwendung datensaetze hinzufuegen (mit primaerschluessel), ich spare mir das ueberpruefen, ob die datensaetze schon vorhanden sind. ich frage einfach die fehlermeldung ab:

    if (pe->m_strError.Find("ORA-00001", 0) == 1)
    

    dann gebe ich eine messagebox aus, dass der datensatz schon existiert, und der benutzer diesen logischerweise nicht mehr einfuegen kann. ORA-00001 ist dabei eben der fehler, der zurueckkommt, wenn du ein datensatz, der mit einem primaerschluessel belegt ist schon existiert.

    Esco



  • Das sieht ja schön einfach aus. 🙂

    Okay, dann muss ich da nach der aktuellen Maske wohl mal dran.

    Oracle - hach schön wärs wenn ich das hätte...
    Dazu findet man wenigstens Doku und nicht nur nen Witz. 😡

    Dankeschön! 🙂



  • Hallo,

    mal ein anderes Problem, wenn ich jetzt mein Programm soweit fertig habe, und möchte jetzt noch mein Programm in so einen schönen Installer verpacken, der mir das Programm auf dem Zielrechner installiert...wie kriege ich es hin, dass mir das Setup bei der Installation auch eine Datenquelle für den SQL Server über die ODBC-Schnittstelle einrichtet..ist sowas möglich oder muss ich es dann per Hand einrichten?

    Gruss,

    chullain



  • Lies dir mal die MSDN zu SQLConfigDataSource durch. Hier im Forum könntest du auch was finden. 🙂
    Ich hatte noch keine Zeit mir das genauer anzuschauen.


Anmelden zum Antworten