[A] Datenbankzugriff mit CRecordset (und CDatabase) - Teil 2
-
CBasisSet: Eine eigene Basisklasse
Sie fragen sich jetzt sicher: "Wozu der Aufwand?"
Natürlich können Sie auch ohne eine eigene Basisklasse mit CRecordset arbeiten.
Allerdings werden Ihnen einige Funktionen bei der täglichen Nutzung als kompliziert zu handhaben oder einfach nur "immer das Selbe zu tippen" auffallen.
Für solche Fälle bietet sich dann eine Basisklasse an.Dort kann man solche Unschönheiten der MFC ausbügeln und CRecordset an die eigenen Bedürfnisse anpassen.
Bei der täglichen Arbeit mit Recordsets haben sich so ein paar nützliche Funktionen ergeben, die mittlerweile in meiner Basisklasse zu finden sind.
IsEmpty
// Gibt zurück, ob Daten enthalten sind. bool CBasisSet::IsEmpty() { if (!IsOpen()) { return true; } return (IsBOF() && IsEOF()); }
Move ohne Fehlermeldung bei leerem Recordset
// Verhindert die Fehlermeldung bei fehlendem IsBOF void CBasisSet::MoveFirst() { if(!IsEmpty()) { CRecordset::MoveFirst(); } }
Update
Eine böse Stolperfalle ist, dass Update FALSE zurückgibt, wenn Sie gar nichts an den Daten im Recordset geändert hatten.
Es dauerte eine Weile, bis ich diesen "Fehler" gefunden hatte und ich habe ihn so umgangen:// Da keine Änderungen nicht gespeichert werden, aber eigentlich auch okay sind wird TRUE // zurückgegeben. BOOL CBasisSet::Update() { if (!IsFieldDirty(NULL)) { // Keine Änderungen ist auch okay! return TRUE; } return CRecordset::Update(); }
Query
Die folgende Funktion erspart Ihnen das ständige Prüfen, ob das Recodset geöffnet ist.
// Damit man nicht aufpassen muss, ob offen ist. bool CBasisSet::Query() { BOOL fResult = FALSE; try { if(!IsOpen()) { fResult = Open(); } else { fResult = Requery(); } } catch (CDBException* e) { throw(e); // Weiterwerfen } return (fResult == TRUE); }
Man kann dieser Funktion auch noch Parameter geben, die den m_strFilter ersetzen oder ergänzen.
Falls Sie also wie ich ein CBasisIdSet machen (von CBasisSet abgeleitet), wo alles behandelt wird, was den Primärschlüssel der Tabelle (die ID) betrifft, könnte das so aussehen:// Damit man nicht aufpassen muss, ob offen ist. bool CBasisIdSet::Query(long f_lID) { if (f_lID > -1) { m_strFilter.Format(_T("[ID] = %d"), f_lID); } return CBasisSet::Query(); }
In eine solche Klasse lassen sich noch viel mehr nützliche Funktionen auslagern, aber das werden Sie schnell selbst bemerken.
-
Todo: Datenquelle per Code einrichten