Strategiefrage: Eine DB-Verbindung für ALLE Datenbankabfragen (Zeitfaktor und wie?)



  • Ähm, das ist glaubich eine Lösung, die ich mir für "wenn ich mal viel Zeit habe" aufhebe.

    Ich werf jetzt nicht alles über den Haufen. 🙄

    Ich bastel grade an meiner Idee, mal gucken obs klappt. 🙂



  • TJA, schlechtes Design wenn du die Datenbankanbindung nicht ändern kannst.



  • Ich muss "nur" die Recordsetklassen ersetzen - aber das ist genug Arbeit, oder? 😕

    33 mehr oder weniger umfangreiche Klassen ist nicht ohne.
    Und bevor ich auf die Idee komme, müsstest du mir den Spaß schon schmackhaft machen. Was sind die megatollen Vorteile gegenüber der CRecordset-Methode. 🙂

    Ich müsste mich ja auch in die Programmierung ohne CRecordset einarbeiten. Deine Wrapperklasse ist doch "nur" für MySql, oder? Ich habe MSDE2000.
    Tutorials dazu sind irgendwie auch recht rar. 😞



  • zu den eingangsfragen:
    ich frage mit einer CDatabase Instanz immer erstmal in der initinstance ab, ob ich ueberhaupt auf die DB zugreifen kann.

    ich kann aber nicht empfehlen, die crecordset-objekte immer offen zu halten. crecordset dabei ua das problem, dass es nicht richtig erkennt, ob die verbindung serverseitig geschlossen wird (kann ja bei einem mehrstuendigen zugriff durchaus ma der fall sein).

    Esco



  • Ich wollte eigentlich nur das CDatabase-Objekt offen halten.

    Das sieht gerade so aus:

    CBasisSet::CBasisSet(CString f_strTabelle)
    	: CRecordset(((CAd3App*)AfxGetApp())->GetDb())
    

    Das gibt aber leider "Fehlermeldungen". 😞
    Kleiner Ausschnitt:

    [...]
    Optional feature not implemented
    State:S1C00,Native:0,Origin:[Microsoft][ODBC SQL Server Driver]
    
    Warning: Driver does not support requested concurrency.
    Optional feature not implemented
    State:S1C00,Native:0,Origin:[Microsoft][ODBC SQL Server Driver]
    
    Warning: Driver does not support requested concurrency.
    Warning: Setting recordset read only.
    [...]
    

    Tja, und so eine "ReadOnly"-Datenbank ist irgendwie nicht so der Bringer. 🤡



  • Mein ODBC_WRAPPER ist aufgebaut wie der MySQL_Wrapper. Lediglich die CONNECT unterscheidet sich.
    Schmackhaft muss ich dir auch nichts machen da ich nichts advon habe wenn du sie verwendest.

    Der Vorteil ist: Man muss sich nicht um das Anlegen von CDatabase-Objekten kümmern. Man legt eine Klasseninstanz an und sendet SQL-Query an die DB.
    Der Connect übergibt man lediglich den DNS_Namen.



  • Wenn du das in den falschen Hals bekommen hast, dann sorry.

    Du schreibst blos davon, als wäre es das Non-Plus-Ultra schlechthin - verrätst aber fast nix von Vor- oder Nachteilen.
    Mal gucken, vielleicht schaue ich es mirmal im Rahmen eines kleineren (privaten) Projektes an - dann kann ich besser was dazu sagen. 🙂

    Zum schon vorhandenen Weg hast du aber wohl keine Ratschläge, oder? 😞



  • Ich habe CDAtabase nie verwendet. Leider ist nicht alles in der MFC super.
    Mein ODBC_Wrapper baut auf dem ODBC_API auf.



  • MSDN Lesen 🙄

    CRecordset bietet explizit die Möglichkeit eine Verbindung
    im Constructor zu übergeben, als CDataBase.
    Damit kann man dann auf die Tabelle zugreifen.
    Mit CDataBase::Open("") öffnet sich sogar der Standard ODBC Dialog.

    Alternativ braucht man nicht unbedingt einen eigenen ODBC Wrapper
    schreiben, es gibt für ODBC die DTL, welche dies alles bereits
    anbietet, und wie ich finde recht gut unterstützt. Die abfragen
    können in STL Container eingelesen werden, oder über einen
    eigenen DBView jeweils abgefragt werden.
    Die DTL ist übrigens auch plattformunabhängig.
    http://dtemplatelib.sourceforge.net/

    Devil



  • @Unix-Tom: Okay, danke. 🙂
    Mal sehen, wann es zeitlich mal passt.

    @devil:

    devil81 schrieb:

    MSDN Lesen

    CRecordset bietet explizit die Möglichkeit eine Verbindung
    im Constructor zu übergeben, als CDataBase.

    Hab ich doch:

    estartu schrieb:

    Das sieht gerade so aus:

    CBasisSet::CBasisSet(CString f_strTabelle)
        : CRecordset(((CAd3App*)AfxGetApp())->GetDb())
    

    Hab ich versucht, geht schief, siehe oben. Das GetDb gibt einen Zeiger auf eine in der InitInstance geöffnete CDatabase zurück.

    devil81 schrieb:

    Mit CDataBase::Open("") öffnet sich sogar der Standard ODBC Dialog.

    Und mit meinem bisher genutzten Connectstring (aus dem Recordset abgefragt) leider auch. 🙄
    Das ist so nicht gewünscht...



  • Hm, dann ist dein Zeiger ungültig.
    Versuchs mal mit einem Gültigen Zeiger auf eine gültige
    Instanz von CRecordset.

    Devil



  • @devil81: Schon versucht die STL in eine DLL zu packen?
    Ich schon und es ging nicht sodaß keine Abhängigkeiten mehr da sind.



  • devil81 schrieb:

    Hm, dann ist dein Zeiger ungültig.
    Versuchs mal mit einem Gültigen Zeiger auf eine gültige
    Instanz von CRecordset.

    Aber das ist doch ein Zeiger auf CDatabase, den ich dem Konstruktor von CRecordset erst übergebe - da habe ich doch noch keine Instanz vom Recordset. 😕



  • estartu_de schrieb:

    devil81 schrieb:

    Hm, dann ist dein Zeiger ungültig.
    Versuchs mal mit einem Gültigen Zeiger auf eine gültige
    Instanz von CRecordset.

    Aber das ist doch ein Zeiger auf CDatabase, den ich dem Konstruktor von CRecordset erst übergebe - da habe ich doch noch keine Instanz vom Recordset. 😕

    Die Frage ist doch, ob der Zeiger zu dem Zeitpunkt schon/noch gültig ist,
    oder ob er überhaupt gültig ist. Dein C-Cast da stellt doch garnicht sicher,
    das überhaupt eine Instanz der Klasse dort korrekt existiert.

    Devil



  • Okay, ich habs jetzt ordentlich gemacht:

    CBasisSet::CBasisSet(CString f_strTabelle)
    	: CRecordset((dynamic_cast<CAd3App*>(AfxGetApp()))->GetDb())
    

    🙂

    Funktioniert aber trotzdem nicht. 😞
    Der Zeiger auf die App ist okay, und die CDatabase-Instanz sieht soweit ich das im Debugger erkennen kann auch gut aus. 😕

    Warum setzt der trotzdem alles auf ReadOnly? 😕

    Achja, damit du dir auch das Erstellen der Verbindung mal angucken kannst:

    BOOL CAd3App::InitInstance()
    {
    	// InitCommonControls() ist für Windows XP erforderlich, wenn ein Anwendungsmanifest
    	// die Verwendung von ComCtl32.dll Version 6 oder höher zum Aktivieren
    	// von visuellen Stilen angibt. Ansonsten treten beim Erstellen von Fenstern Fehler auf.
    	InitCommonControls();
    
    	if (!m_dbAd.OpenEx("DSN=audiodatic;UID=sa;PWD=manager", CDatabase::noOdbcDialog))
    	{
    		CLog::Melde(_T("Es konnte keine Verbindung mit der Datenbank hergestellt werden, das Programm wird beendet."));
    		return FALSE;
    	}
    
    	// Anmeldedialog anzeigen
    	CAnmeldeDlg dlg(m_rBenutzer); // Erst nach dieser Zeile kommen die ersten Datenbankzugriffe.
    [...]
    


  • Hm, it a feature, not a bug 😃

    vielleicht hilft CDatabase::noOdbcDialog| ~CDatabase::ReadOnly *g*

    Hast du es schon mal mit Open versucht ?
    Seh gerade das Readonly könnte man im Recordset mit einem Open evtl. wieder aus
    der Welt schaffen, falls die Database und MS das zuläst.

    Devil



  • devil81 schrieb:

    vielleicht hilft CDatabase::noOdbcDialog| ~CDatabase::ReadOnly *g*

    Args, du grinst extra noch und ich Horsti probiers trotzdem aus. 🙄
    Nein, das funktioniert jedenfalls überhaupt nicht. 🤡

    devil81 schrieb:

    Seh gerade das Readonly könnte man im Recordset mit einem Open evtl. wieder aus
    der Welt schaffen, falls die Database und MS das zuläst.

    Ich mach doch für jedes Recordset noch ein Open - oder was meinst du jetzt?
    Sorry, ich stehe heute und besonders bei Datenbankzeugs total auf dem Schlauch...

    So sieht meine Funktion aus, mit der ich JEDES Recordset öffne:

    try
    	{
    		if(!IsOpen())
    		{
    			fResult = Open();
    		}
    		else
    		{
    			fResult = Requery();
    		}
    	}
    	catch (CDBException* e)
    	{
    		CLog::Log(LOG_NR_DB_FEHLER, e->m_strError);
    		throw(e); // Weiterwerfen
    	}
    

    Ich sehe bei der Hilfe zu Open aber nichts, was mit ReadOnly oder dessen Aufhebung zu tun hat. 😕

    Jetzt gucke ich mal, ob der Tausch von OpenEx (das fand ich wegen der geringen Parameteranzahl sympatisch) gegen Open was hilft. 🙂



  • Schau dir mal den MSDN Artikel zu CRecordset::Open an.
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_mfc_crecordset.3a3a.crecordset.asp

    Ich hab keine ahnung was AFX_DB_USE_DEFAULT_TYPE für einen wert hat,
    evtl. musst du da CRecordSet::dynaset oder so hinmachen. ReadOnly könnte Default sein 😉

    Devil



  • Es lag am OpenEx.
    Ich mache das jetzt so:

    if (!m_dbAd.Open("audiodatic", FALSE, FALSE, "ODBC;UID=sa;PWD=manager"))
    

    Und momentan gibt es keine offensichtlichen Probleme... 😃

    Wie schon gesagt: Von den Möglichkeiten bei CRecordset::Open schien keine zu passen:

    CRecordset::dynaset
    CRecordset::snapshot
    CRecordset::dynamic
    CRecordset::forwardOnly

    Der default hatte ja funktioniert und funktioniert jetzt wieder. 🙂

    Aber vielen Dank fürs geduldige Ausdiskutieren. 👍

    Hast du vielleich noch nen Zusatztip, wo man leicht verständliche Tutorials zur fehlersicheren Datenbanknutzung bekommt?
    Ich bin bisher dank "Unverständnis" doch äußerst sparsam mit try...catch. 😞

    Da muss es doch auch irgendwo eine Anleitung geben, oder? 😕



  • Alles was schiefgehen kann sollte einen Try Catch Block haben 😉
    Dann musst du aber auch noch die richtige Exception fangen.
    Für den Anfang dürfte aber in der MFC CException zu fangen reichen.

    Jens


Anmelden zum Antworten