CDatabase
Öffnen und Schliessen
Nach der Erzeugung per Konstruktor, wird die Verbindung zur ODBC-Schnittstelle mit den Memberfunctions Open oder OpenEx hergestellt.
virtual BOOL Open( LPCTSTR strDataSourceName, BOOL bExclusive = FALSE, BOOL bReadOnly = FALSE, LPCTSTR lpszConnectString = "ODBC;", BOOL bUseCursorLib = TRUE );
strDataSourceName ist der Name, der für die Datenbank im ODBC genannt ist. Ist er NULL, wird er im ConnectString angegeben. Der ConnectString enthält DataSource, Username und Kennwort durch Semikolon getrennt z. B. , "DSN=MeineDatenbank;UID=Arnold;PWD=sagichnicht". Wird statt dieses Parameters 0 übergeben, erscheint ein Verbindungsdialog.
Alternativ (und empfohlen) ist der Aufruf OpenEx
virtual BOOL OpenEx( LPCTSTR lpszConnectString, DWORD dwOptions = 0 );
Der ConnectString enthält DataSource, Username und Kennwort durch Semikolon getrennt z. B. , "DSN=MeineDatenbank;UID=Arnold;PWD=sagichnicht". Wird statt dieses Parameters 0 übergeen, erscheint ein Verbindungsdialog.
Der Parameter Optionen kann die folgenden Werte (auch geodert) annehmen:
CDatabase::openExclusive | nicht unterstützt |
CDatabase::openReadOnly | nur in der Datenbank lesen |
CDatabase::useCursorLib | Lade die ODBC Cursor Library DLL zur Verhinderung von DynaSets |
CDatabase::noOdbcDialog | zeige keinesfalls den Verbindungsdialog, auch wenn noch Informationen fehlen |
CDatabase::forceOdbcDialog | zeige immer den ODBC-Verbindungsdialog |
Natürlich gibt es auch einen Close-Aufruf. Er hat keine Parameter und löst einen Rollback auf alle laufenden Aktionen und Transaktionen aus. Es empfielt sich, vor Schliessen der Database erst alle Recordsets zu schliessen.
Transaktionen
Mit der Funktion BOOL CDatabase::CanTransact() stellt man fest, ob der ODBC-Treiber überhaupt Transaktionen handhaben kann. Mit dem Aufruf von BOOL CDatabase::BeginTrans(); wird die Transaktion eingeleitet. Es empfielt sich, vor dem ersten Zugriff auf den Recordset BeginTrans aufzurufen. Die Transaktion wird abgeschlossen mit BOOL CDatabase::CommitTrans(); oder zurückgesetzt mit BOOL CDatabase::Rollback();.Mit dem Aufruf void CDatabase::ExecuteSQL( LPCSTR lpszSQL ); können Datenbankkommandos abgesetzt werden, die keine Ergebnisse in Recordsets zurückliefern.
CRecordset
Der Recordset ist in zwei Ausprägungen vorhanden, dem Dynaset und Schnappschuss. Der Schnappschuss gibt den einmaligen, aktuellen Zustand der Datenbank wieder. Der Dynaset, der nicht von allen Treibern unterstützt wird, synchronisiert die Daten, die von anderen Anwendern verändert werden.Typischerweise wird ein applikationseigener Recordset von CRecordset abgeleitet.
Erzeugen und Öffnen eines Recordsets
Der Kontruktor benötigt die Adresse der CDatabase-Variablen.CRecordset::CRecordset( CDatabase* pDatabase = NULL);Durch Open wird der Recordset mit einem SQL-Statement verbunden.
virtual BOOL Open( UINT nTyp = AFX_DB_USE_DEFAULT_TYPE, LPCTSTR strSQL = NULL, DWORD dwOptions = none );
Der Typ kann folgende Werte annehmen:
- AFX_DB_USE_DEFAULT_TYPE
- Der Defaultwert des Treibers
- CRecordset::dynaset
- Die Auswahl und Reihenfolge der Sätze erfolgt bei Eröffnung. Änderungen anderer Anwender werden bei jeder fetch-Operation sichtbar.
- CRecordset::snapshot (default)
- Die Auswahl und Reihenfolge der Sätze erfolgt bei Eröffnung. Änderungen anderer Anwender werden nur durch Schliessen und wieder Öffnen sichtbar.
- CRecordset::dynamic
- Die Auswahl und Reihenfolge der Sätze so wie auch Änderungen anderer Anwender werden bei jeder fetch-Operation sichtbar. Viele ODBC-Treiber unterstützen dies nicht.
- CRecordset::forwardOnly
- Ein Nur-Lese Recordset, der auch nur vorwärts lesen kann.
strSQL ist der Name einer Tabelle, ein SELECT-Statement (mit WHERE-Klausel) oder ein CALL-Statement für eine Stored-Procedure.
dwOptions kann eine oder mehrere der folgenden sein:
- CRecordset::none
- Der Recordset kann mit Edit, Delete und AddNew verändert werden.
- CRecordset::appendOnly
- Der Recordset darf nur durch AddNew und nicht per Edit oder Delete verändert werden.
- CRecordset::readOnly
- Recordset nur zum Lesen öffnen.
- CRecordset::optimizeBulkAdd
- Optimiert das Hinzufügen mehrerer Sätze bei Verwendung eines vorbereiteten SQL-Statement.
- CRecordset::useMultiRowFetch
- Damit können mehrere Zeilen in einer einzigen Fetch-Operation geladen werden.
- CRecordset::skipDeletedRecords
- Überspringt gelöschte Sätze, wenn durch den Recordset navigiert wird. Die Geschwindigkeit wird in bestimmten Fällen reduziert.
- CRecordset::useBookmarks
- Es werden Bookmarks verwendet, wenn der Treiber dies unterstützt.
- CRecordset::noDirtyFieldCheck
- Schaltet das automatische Dirty Field Checking (double buffering)aus.
- CRecordset::executeDirect
- Verwendet keine vorbereiteten SQL-Statements.
- CRecordset::useExtendedFetch
- Implementiert SQLExtendedFetch statt SQLFetch.
- CRecordset::userAllocMultiRowBuffers
- Der Anwender wird den Speicher für die Daten alloziieren.
Update eines Recordset
Zunächst wird mit den Befehlen AddNew bzw Edit die Änderung eingeleitet. Die Felder werden besetzt und anschliessend mit Update bestätigt.
- AddNew()
- AddNew erzeugt einen neuen, leeren Satz und verwendet dazu die Felder des Recordsets. Die Datenfelder werden belegt und per Update in die Datenquelle geschrieben.
- Edit()
- Mit Edit werden Änderungen im aktuellen Satz eingeleitet. Die Recordset-Variablen werden direkt geändert. Durch den Aufruf von Update gehen die &Aunderungen an die Datenquelle.
- Delete()
- Löscht den aktuellen Datensatz.
Navigieren
- void MoveFirst( );
- Durch diesen Aufruf wird der erste Satz des Recordset der aktuelle Satz. Es ist nicht erforderlich MoveFirst direkt nach dem Öffnen des Recordset zu rufen.
- void MoveLast( );
- Sofern nicht bulk-fetching gesetzt ist, wird der letzte Satz im Recordset der aktuelle.
- void MoveNext( );
- wechsele den aktuellen Satz zum nächsten im Recordset. Gelöschte Sätze werden nicht unbedingt übersprungen. Die IsDeleted()-Funktion sollte benutzt werden.
- void MovePrev( );
- wechsele den aktuellen Satz zum vorherigen im Recordset.
Zugriff auf die Felder
void GetFieldValue( LPCTSTR lpszName, CDBVariant& varValue, short nFieldType = DEFAULT_FIELD_TYPE ); void GetFieldValue( short nIndex, CDBVariant& varValue, short nFieldType = DEFAULT_FIELD_TYPE ); void GetFieldValue( LPCTSTR lpszName, CString& strValue ); void GetFieldValue( short nIndex, CString& strValue );
Parameter
- lpszName
- Feldname
- varValue
- Eine Referenz auf ein CDBVariant-Objekt, das den Feldwert hält
- nFieldType
- Der ODBC C-Datentyp des Feldes. Bei Angabe von DEFAULT_FIELD_TYPE wird der C-Typ aus dem SQL Datentyp nach der folgenden Tabelle ermittelt.
- nIndex
- Der Feldindex (nullbasierend)
- strValue
- Referenz auf ein CString, das den Feldinhalt als String enthält, ganz gleich, welchen Datentyp das Feld hat.
CDatabase db; db.OpenEx( NULL, CDatabase::forceOdbcDialog ); CRecordset rs( &db ); rs.Open( CRecordset::forwardOnly, _T( "SELECT * FROM MeineTabelle" ) ); CDBVariant Wert; int n = rs.GetODBCFieldCount( ); while( !rs.IsEOF() ) { for( int i = 0; i < n; i++ ) { rs.GetFieldValue( i, Wert ); . . . } rs.MoveNext( ); } rs.Close( ); db.Close( );
Informationen zu den Feldern
void CRecordset::GetODBCFieldInfo( LPCTSTR lpszName, CODBCFieldInfo& fieldinfo ); void CRecordset::GetODBCFieldInfo( short nIndex, CODBCFieldInfo& fieldinfo );
- lpszName
- Der Feldname
- fieldinfo
- Ein Zeiger auf eine CODBCFieldInfo Struktur
- nIndex
- Feldindex (nullbasierend)
Die CODBCFieldInfo Struktur
struct CODBCFieldInfo { CString m_strName; SWORD m_nSQLType; UDWORD m_nPrecision; SWORD m_nScale; SWORD m_nNullability; };
- m_strName
- Feldname
- m_nSQLType
- Der SQL-Datentyp des Feldes.
- m_nPrecision
- Die maximale Genauigkeit des Feldes.
- m_nScale
- Die Grösse des Feldes.
- m_nNullability
- Gibt an, ob das Feld Nullwerte akzeptiert (SQL_NULLABLE) oder nicht (SQL_NO_NULLS).