16 311 312 313 317 321 Von DAO zu ADO Grundlagen Öffnen einer Datenbank Zugriff auf die Daten per Recordset Ausführen von Abfragen DAO in Access-Projekten Wenn Sie DAO-Programme zu ADO umsetzen müssen oder mit DAO vertraut sind, so sind Ihnen vielleicht die folgenden Beschreibungen und Listings hilfreich, die die entsprechenden Befehle von DAO und ADO gegenüberstellen. Viele DAO-Befehle haben keine Entsprechung in ADO oder sind aufgrund der neuen Strukturen von Access-Projekten nicht mehr notwendig oder nicht mehr einsetzbar. Insbesondere alle Befehle zum Anlegen von Tabellen und Abfragen können nicht umgesetzt werden, da ADO nicht über entsprechende Befehle verfügt. Für MDB-Datenbanken auf Basis der Jet-Engine können für das Anlegen von Tabellen und Abfragen die Routinen der »Microsoft ADO Extensions for DDL and Security«-Bibliothek (ADOX) verwendet werden. ADOX funktioniert aber so gut wie nicht mit dem SQL Server-OLE DB-Provider. Das Gleiche gilt für die DAO-Replikationsbefehle, die für die Jet-ADO-Programmierung in die Bibliothek JRO, »Microsoft Jet and Replication Objects«, ausgelagert sind. Auch diese Bibliothek kann nicht für SQL Server/MSDE eingesetzt werden. Grundlagen Das Objektmodell von DAO ist umfangreicher als das ADO-Modell, denn DAO ermöglicht neben dem Zugriff auf die Daten auch die Verwaltung beispielsweise von Benutzern, Benutzergruppen und vielen weiteren Strukturen, die von der Jet-Engine unterstützt werden. ADO dagegen ist eine reine Datenzugriffsschnittstelle und bietet nur die Objekte an, die direkt für den Datenzugriff benötigt werden. Zur Verwaltung von Benutzern, Benutzergruppen und vielem anderen müssen entweder entsprechende Transact-SQL-Befehle oder andere Programmier- 311 Nicol/Albrech: Microsoft Access-Projekte mit SQL Server 7.0/2000. Microsoft Press 2001. ISBN: 3-86063-614-6 schnittstellen wie beispielsweise SQLDMO (siehe Kapitel 22) eingesetzt werden. Die folgende Tabelle stellt die Objekte der beiden Datenzugriffsschnittstellen gegenüber. DAODAO-Objekt DBEngine Workspace Database Recordset User Group TableDef QueryDef Relation Container Document - ADOADO-Objekt Connection Recordset Command (nur zur Ausführung von Abfragen) Record Stream Tabelle 16.1: Gegenüberstellung der wichtigsten DAO- und ADO-Objekte Wir möchten Ihnen in diesem Kapitel die wichtigsten DAO- und ADO-Objekte in kleinen Beispielprogrammen gegenüberstellen. Öffnen einer Datenbank Um auf eine Datenbank zugreifen zu können, muss in DAO ein Database-Objekt verwendet werden. ADO greift über eine Connection auf eine Datenbank zu. Für DAO lässt sich mit der Funktion CurrentDB die aktuell geladene Datenbank ermitteln, während für ADO die aktuelle Verbindung des Access-Projekts zur SQL Server-/MSDE-Datenbank über CurrentProject.Connection zur Verfügung steht. In DAO schreiben Sie dazu die folgenden Befehle: Dim db As DAO.Database Set db = CurrentDB In ADO formulieren Sie: Dim cnn As ADODB.Connection Set cnn = CurrentProject.Connection Beachten Sie bei ADO, dass normalerweise ein Connection-Objekt mit New erstellt werden muss, also beispielsweise Set cnn = New ADODB.Connection Nur bei einer Zuweisung von CurrentProject.Connection ist dies nicht notwendig, da das Connection-Objekt des CurrentProject-Objekts schon existiert. 312 Kapitel 16 Nicol/Albrech: Microsoft Access-Projekte mit SQL Server 7.0/2000. Microsoft Press 2001. ISBN: 3-86063-614-6 Zugriff auf die Daten per Recordset Sowohl DAO als auch ADO verwenden Recordsets für den eigentlichen Zugriff auf die Daten. In DAO verwenden Sie die folgenden Befehle: Dim db As DAO.Database Dim rec As DAO.Recordset Set db = CurrentDB Set rec = db.OpenRecordset("SELECT * FROM tblFilme", dbOpenDynaset) Die ADO-Variante lautet: Dim cnn As ADODB.Connection Dim rs As ADODB.Recordset Set cnn = CurrentProject.Connection Set rs = New ADODB.Recordset rs.Open "SELECT * FROM tblFilme", _ ActiveConnection:=cnn, _ CursorType:=adOpenStatic, _ LockType:=adLockOptimistic Die folgende Tabelle stellt die Parameter gegenüber, die zum Öffnen eines Recordsets angegeben werden können. DAO dbOpenDynaset dbOpenSnapshot dbOpenForwardOnly dbOpenTable - ADO CursorType = adOpenStatic, LockType = adLockOptimistic CursorType = adOpenDynamic, LockType = adLockOptimistic CursorType = adOpenStatic, LockType = adLockReadOnly CursorType = adOpenForwardOnly, LockType = adLockReadOnly CursorType = adOpenStatic, LockType = adLockOptimistic, Options = adCmdTableDirect CursorType = adOpenDynamic, LockType = adLockOptimistic, Options = adCmdTableDirect CursorType = adOpenKeyset Tabelle 16.2: Recordset-Typen im Vergleich Bewegen des Datensatzzeigers DAO und ADO bewegen den Datensatzzeiger mit den Methoden MoveNext, MovePrevious, MoveFirst und MoveLast durch das Recordset. Mithilfe der Funktionen EOF und BOF fragen Sie bei DAO wie auch bei ADO ab, ob das Ende oder der Anfang des Recordsets erreicht ist. Hinzufügen, Bearbeiten und Löschen von Daten In diesem Abschnitt stellen wir Ihnen die Befehle zum Hinzufügen, Bearbeiten und Löschen von Datensätzen vor. Sie unterscheiden sich für DAO und ADO nur in Details. Zugriff auf die Daten per Recordset 313 Nicol/Albrech: Microsoft Access-Projekte mit SQL Server 7.0/2000. Microsoft Press 2001. ISBN: 3-86063-614-6 Hinzufügen von Datensätzen DAO und ADO verwenden die Methode AddNew zum Hinzufügen eines neuen Datensatzes. Bei ADO wird der neu hinzugefügte Datensatz automatisch zum aktuellen Datensatz, bei DAO zeigt der Datensatzzeiger immer noch auf den Datensatz, auf den er vor dem Hinzufügen zeigte. Mit der Methode Update wird bei beiden Datenzugriffsschnittstellen der neue Datensatz gespeichert. Im folgenden Listing ist die Variante für DAO aufgeführt: ... ' DAO Dim rec As DAO.Recordset Set rec = CurrentDB.OpenRecordset("SELECT * FROM tlbFilme", dbOpenDynaset) ' Neuen Datensatz hinzufügen rec.Addnew rec!Filmtitel = "Erin Brockovich" rec!FSK = 6 rec!Länge = 131 rec.Update rec.Close ... Der ADO-Code unterscheidet sich fast nicht: ... ' ADO Dim rec As ADODB.Recordset Set rec = New ADODB.Recordset rec.Open "SELECT * FROM tblFilme", CurrentProject.Connection, adOpenStatic, adLockOptimistic ' Neuen Datensatz hinzufügen rec.Addnew rec!Filmtitel = "Erin Brockovich" rec!FSK = 6 rec!Länge = 131 rec.Update rec.Close ... Bearbeiten von Datensätzen Die Bearbeitung eines Datensatzes unterscheidet sich geringfügig für DAO und ADO. Um mit DAO die Inhalte des aktuellen Datensatzes verändern zu können, muss die Methode Edit eingesetzt werden. Mit ADO können Sie die Inhalte direkt manipulieren. Um die Änderungen zu speichern, muss in DAO die Methode Update aufgerufen werden. In ADO können Sie ebenfalls Update verwenden, allerdings werden die Änderungen automatisch 314 Kapitel 16 Nicol/Albrech: Microsoft Access-Projekte mit SQL Server 7.0/2000. Microsoft Press 2001. ISBN: 3-86063-614-6 gespeichert, wenn Sie den Datensatzzeiger zu einem anderen Datensatz bewegen. Möchten Sie die Änderungen nicht speichern, so rufen Sie die Methode CancelUpdate auf. ... ' DAO Dim rec As DAO.Recordset Set rec = CurrentDB.OpenRecordset("SELECT * FROM tlbFilme", dbOpenDynaset) ' Ersten Datensatz bearbeiten rec.MoveFirst rec.Edit rec!Zusatztext = "Bla Bla Bla" If MsgBox("Datensatz speichern?", vbYesNo) = vbYes Then rec.Update End If ' Zum nächsten Datensatz weitergehen rec.MoveNext ... Das Beispiel sieht mit ADO folgendermaßen aus: ... ' ADO Dim Rec As ADODB.Recordset Set Rec = New ADODB.Recordset rec.Open "SELECT * FROM tblFilme", CurrentProject.Connection, adOpenStatic, adLockOptimistic ' Ersten Datensatz bearbeiten rec.MoveFirst rec!Zusatztext = "Bla Bla Bla" If MsgBox("Datensatz speichern?", vbYesNo) = vbYes Then rec.Update Else rec.CancelUpdate End If ' Zum nächsten Datensatz weitergehen rec.MoveNext ... Löschen von Datensätzen Sowohl in DAO als auch in ADO löschen Sie den aktuellen Datensatz mithilfe der Methode Delete. Zugriff auf die Daten per Recordset 315 Nicol/Albrech: Microsoft Access-Projekte mit SQL Server 7.0/2000. Microsoft Press 2001. ISBN: 3-86063-614-6 Suchen von Daten In DAO werden die Methoden FindFirst, FindLast, FindNext und FindPrevious zum Auffinden von Datensätzen in einem Recordset verwendet. In ADO steht Ihnen dazu die Methode Find zur Verfügung, die mithilfe eines Parameters so gesteuert wird, dass sie die gleiche Funktionalität wie die vier DAO-Methoden hat. Die folgende Tabelle stellt die Methoden gegenüber. DAO recDAO.FindFirst Kriterium recDAO.FindLast Kriterium recDAO.FindNext Kriterium recDAO.FindPrevious Kriterium ADO recADO.MoveFirst recADO.Find Kriterium, 0, adSearchForward recADO.MoveLast recADO.Find Kriterium, 0, adSearchBackward recADO.Find Kriterium, 1, adSearchForward recADO.Find Kriterium, 1, adSearchBackward Tabelle 16.3: Gegenüberstellung der Suchmethoden Der zweite Parameter SkipRows der ADO-Find-Methode gibt an, wie viele Datensätze übersprungen werden sollen, bevor das Suchkriterium angewendet werden soll. Die ADO-Methode Seek zum Suchen von Datensätzen mithilfe eines Indexes kann nicht mit dem SQLOLEDB-Provider eingesetzt werden. Sollten Sie Seek in Ihren DAO-Programmen verwenden, müssen Sie dies für Access-Projekte mit Find umschreiben. Filtern von Daten DAO und ADO verwenden beide die Eigenschaft Filter, um die Daten eines Recordsets nach einem Kriterium einzuschränken. Allerdings bestehen Unterschiede zwischen den beiden Datenzugriffsschnittstellen, wie die Filter-Eigenschaft eingesetzt wird. Wird ein DAO-Recordset mithilfe der Filter-Eigenschaft gefiltert, so wird ein zweites Recordset benötigt, um auf die gefilterten Daten zuzugreifen. ... Dim rec As DAO.Recordset Dim recFilter As DAO.Recordset Set rec = CurrentDB.OpenRecordset("SELECT * FROM tblFilme", dbOpenDynaset) ' Selektiere alle Filme, die länger als zwei Stunden laufen rec.Filter = "Länge > 120" ' Neues Recordset für die gefilterten Daten Set recFilter = rec.OpenRecordset(dOpenDynaset) Do Until recFilter.EOF Debug.Print recFilter!Filmtitel recFilter.MoveNext Loop recFilter.Close rec.Close ... Bei einem ADO-Recordset wird die Filter-Eigenschaft auf das Recordset selbst angewandt, es ist kein zweites Recordset notwendig. 316 Kapitel 16 Nicol/Albrech: Microsoft Access-Projekte mit SQL Server 7.0/2000. Microsoft Press 2001. ISBN: 3-86063-614-6 ... Dim rec As ADODB.Recordset Set rec = New ADODB.Recordset rec.Open "SELECT * FROM tblFilme", CurrentProject.Connection, adOpenStatic, adLockOptimistic ' Selektiere alle Filme, die länger als zwei Stunden laufen rec.Filter = "Länge > 120" Do Until rec.EOF Debug.Print rec!Filmtitel rec.MoveNext Loop rec.Close ... Sortieren von Daten Das nachträgliche Sortieren der Daten eines Recordsets kann in DAO und ADO mithilfe der Eigenschaft Sort erfolgen. Sort wird wie die oben beschriebene Eigenschaft Filter eingesetzt, d.h., es gibt Unterschiede in der Anwendung zwischen DAO und ADO. Lesezeichen Sowohl DAO als auch ADO unterstützen prinzipiell das Setzen von Lesezeichen, Bookmarks. Ob Bookmarks für ein bestimmtes Recordset verwendet werden können, hängt davon ab, mit welchen Optionen das Recordset geöffnet wurde. In DAO können Sie mithilfe der Eigenschaft Bookmarkable, in ADO über die Funktion Supports(adBookmark) abfragen, ob das Recordset Lesezeichen unterstützt. DAO und ADO verwenden die gleiche Syntax für die Arbeit mit Lesezeichen. Beachten Sie dabei, dass DAO-Bookmarks in String-Variablen gespeichert werden, während ADO-Bookmarks Variablen vom Typ Variant erfordern. ... Dim vLesezeichen As Variant ' Lesezeichen des aktuellen Datensatzes merken vLesezeichen = rec.Bookmark ... ' Den gemerkten Datensatz zum aktuellen Datensatz machen rec.Bookmark = vLesezeichen ... Ausführen von Abfragen In der Behandlung von Abfragen unterscheiden sich DAO und ADO erheblich. Während mit DAO-QueryDef-Objekten Abfragen erstellt und ausgeführt werden können, dienen die ADOCommand-Objekte nur zur Ausführung von Abfragen. QueryDef- bzw. Command-Objekte werden in den meisten Fällen eingesetzt, um Aktionsabfragen oder Abfragen mit Parametern auszuführen. Ausführen von Abfragen 317 Nicol/Albrech: Microsoft Access-Projekte mit SQL Server 7.0/2000. Microsoft Press 2001. ISBN: 3-86063-614-6 Verwaltung von Abfragen Ein DAO-QueryDef-Objekt beschreibt eine Abfrage in einer MDB-Datenbank. In der Auflistung QueryDefs sind die QueryDef-Objekte für alle Abfragen aufgeführt. DAO ermöglicht das Hinzufügen neuer Objekte an die QueryDefs-Auflistung, also das Erstellen neuer Abfragen in der MDBDatenbank. Mit ADO dienen Command-Objekte nur zur Ausführung von Abfragen. Die Verwaltung von Abfragen in einer MDB-Datenbank oder einem Access-Projekt wird über die Auflistungen AllQueries, AllStoredProcedures und AllViews des Access-CurrentData-Objekts vorgenommen. Die Auflistungen bestehen aus AccessObject-Objekten, es können keine neuen Objekte aus einem VBA-Programm heraus erstellt werden. Einfache Auswahlabfragen Wir möchten Ihnen in diesem Abschnitt beschreiben, wie Sie einfache Auswahlabfragen ausführen können, die eine Ergebnismenge in einem Recordset zurückliefern. Um mit DAO die vordefinierte Abfrage Abfrage1 auszuführen, schreiben Sie den folgenden Code, der in der Variablen rec ein Recordset mit Daten ermittelt. ... ' DAO Dim db As DAO.Database Dim qry As DAO.QueryDef Dim rec As DAO.Recordset Set db = CurrentDB Set qry = db.QueryDefs("Abfrage1") Set rec = qry.OpenRecordset(dbOpenDynaset) ... In ADO wird der Aufruf wie folgt codiert, wobei als CommandText für das Command-Objekt eine SELECT-Abfrage bzw. der Aufruf einer Sicht oder gespeicherten Prozedur angegeben werden kann. Beachten Sie, dass das Ergebnis-Recordset nur gelesen werden kann, es können im Unterschied zu DAO keine Änderungen an den Daten vorgenommen werden. ... ' ADO Dim cnn As ADODB.Connection Dim cmd As ADODB.Command Dim rec As ADODB.Recordset Set cnn = CurrentProject.Connection Set cmd = New ADODB.Command Set cmd.ActiveConnection = cnn cmd.CommandText = "Sicht1" Set rec = cmd.Execute ... 318 Kapitel 16 Nicol/Albrech: Microsoft Access-Projekte mit SQL Server 7.0/2000. Microsoft Press 2001. ISBN: 3-86063-614-6 Abfragen mit Parametern Um mit DAO Abfragen mit Parametern bzw. mit ADO gespeicherte Prozeduren mit Parametern ausführen zu können, werden die Parameters-Auflistungen von QueryDef- bzw. Command-Objekten eingesetzt. ... ' DAO Dim Dim Dim Dim db As DAO.Database qry As DAO.QueryDef rec As DAO.Recordset par As DAO.Parameter Set db = CurrentDb Set qry = db.QueryDefs("Abfrage1") For Each par In qry.Parameters par.Value = InputBox(par.Name) Next Set rec = qry.OpenRecordset(dbOpenForwardOnly) Do Until rec.EOF Debug.Print rec(0).Value rec.MoveNext Loop ... Programmieren Sie die gleiche Funktionalität in ADO, so gehen Sie wie im folgenden Listing gezeigt vor. Beachten Sie dabei, dass ADO Ein- und Ausgabeparameter kennt. ... 'ADO Dim Dim Dim Dim cnn cmd rec par As As As As ADODB.Connection ADODB.Command ADODB.Recordset ADODB.Parameter Set cnn = CurrentProject.Connection Set cmd = New ADODB.Command Set cmd.ActiveConnection = cnn cmd.CommandType = adCmdStoredProc cmd.CommandText = "Film" ' Refresh funktioniert nur ab ADO 2.6, siehe Kapitel 13 cmd.Parameters.Refresh For Each par In cmd.Parameters If par.Direction = adParamInput Or par.Direction = adParamInputOutput Then par.Value = InputBox(par.Name) End If Next Ausführen von Abfragen 319 Nicol/Albrech: Microsoft Access-Projekte mit SQL Server 7.0/2000. Microsoft Press 2001. ISBN: 3-86063-614-6 Set rec = cmd.Execute Do Until rec.EOF Debug.Print rec(0).Value, rec(1).Value rec.MoveNext Loop ... Aktionsabfragen In den meisten Fällen werden QueryDef- und Command-Objekte verwendet, um Aktionsabfragen auszuführen, die keine Ergebnismengen zurückliefern. Um mit DAO die Aktualisierungsabfrage Preiserhöhung auszuführen, programmieren Sie beispielsweise: ... ' DAO Dim db As DAO.Database Dim qry As DAO.QueryDef Set db = CurrentDb Set qry = db.QueryDefs("Preiserhöhung") qry.Execute ... Alternativ können Sie die Execute-Methode des Database-Objekts verwenden, um so kurz db.Execute "Preiserhöhung" zu schreiben. Mit ADO formulieren Sie wie folgt: ... Dim cnn As ADODB.Connection Dim cmd As ADODB.Command Set cnn = CurrentProject.Connection Set cmd = New ADODB.Command Set cmd.ActiveConnection = cnn cmd.CommandType = adCmdStoredProc cmd.CommandText = "Preiserhöhung" cmd.Execute ... Als weitere Variante können Sie auch die Execute-Methode des Connection-Objekts verwenden: cnn.Execute "Preiserhöhung" 320 Kapitel 16 Nicol/Albrech: Microsoft Access-Projekte mit SQL Server 7.0/2000. Microsoft Press 2001. ISBN: 3-86063-614-6 DAO in AccessAccess-Projekten Mit einem Trick können Sie vorhandenen DAO-Code auch in Access-Projekten verwenden. Dabei wird ein DAO-Database-Objekt verwendet, das eine ODBC-Verbindung zur SQL Server/MSDE-Datenbank aufbaut, mit der das Projekt verbunden ist. Nach unserer Erfahrung kann ein Großteil von vorhandenen DAO-Programmen mit diesem Trick ausgeführt werden. Wir haben ihn für einige Projekte für eine Übergangszeit benutzt, um beim Umsetzen von MDBDatenbankapplikationen zu Access-Projekten schnell zu funktionierenden Applikationen zu kommen. Die im folgenden Listing gezeigte Funktion DAODatabase gibt ein DAO.Database-Objekt zurück. Das Database-Objekt verweist nicht auf eine Access-MDB-Datenbank, sondern mithilfe einer ODBCVerbindungszeichenkette, die aus den Daten der Verbindungszeichenfolge der CurrentProject.Connection-Eigenschaft abgeleitet wurde, auf die SQL Server-/MSDE-Datenbank, mit der das aktuelle Projekt verbunden ist. Public Function DAODatabase() As DAO.Database Dim cnn As ADODB.Connection Dim dbDAO As DAO.Database Dim strConnect As String Set cnn = CurrentProject.Connection ' Basiert die Verbindung auf MSDataShape- oder SQLOLEDB-Provider? If InStr(cnn.Provider, "MSDataShape") > 0 Or InStr(cnn.Provider, "SQLOLEDB") > 0 Then ' Zusammensetzen der Verbindungszeichenkette strConnect = "ODBC;driver=SQL Server;server=" & cnn.Properties("Data Source") & ";" ' Name der Datenbank strConnect = strConnect & "database=" & cnn.Properties("Initial Catalog") & ";" ' SQL Server- oder Windows-Sicherheit? If cnn.Properties("Integrated Security") = "SSPI" Then strConnect = strConnect & "Trusted_Connection=Yes;" Else strConnect = strConnect & "UID=" & cnn.Properties("User ID") & ";" strConnect = strConnect & "PWD=" & cnn.Properties("Password") & ";" End If Else MsgBox "DAO-Datenbank kann nicht geöffnet werden!" Set DAODatabase = Nothing Exit Function End If ' Neue Datenbank öffnen Set dbDAO = DBEngine.OpenDatabase("", False, False, strConnect) Set DAODatabase = dbDAO End Function Mit der folgenden Prozedur können Sie die Funktion DAODatabase testen. DAO in Access-Projekten 321 Nicol/Albrech: Microsoft Access-Projekte mit SQL Server 7.0/2000. Microsoft Press 2001. ISBN: 3-86063-614-6 Sub DAO_Test() Dim db As DAO.Database Dim rec As DAO.Recordset Set db = DAODatabase() Set rec = db.OpenRecordset("select * from tblFilme", dbOpenForwardOnly) Do Until rec.EOF Debug.Print rec!Filmtitel rec.MoveNext Loop Set db = Nothing End Sub 322 Kapitel 16 Nicol/Albrech: Microsoft Access-Projekte mit SQL Server 7.0/2000. Microsoft Press 2001. ISBN: 3-86063-614-6