Was ist der grundlegende Unterschied zwischen DAO und ADO?
Die Frage kommt immer wieder.
Zwei Technologien. Beide für Datenbankzugriff. Beide in VBA verfügbar.
DAO (Data Access Objects):
Entwickelt von Microsoft in den frühen 90ern. Speziell für Jet/ACE-Datenbanken (Access).
Optimiert für lokale MDB/ACCDB-Dateien.
ADO (ActiveX Data Objects):
Kam Mitte der 90er. Universal-Schnittstelle für verschiedene Datenbanken.
Basiert auf OLE DB. Funktioniert mit SQL Server, Oracle, MySQL, Access.
Kern-Unterschied:
DAO ist spezialisiert. ADO ist universell.
DAO kennt Access-Interna. ADO kennt sie nicht.
Welche Technologie sollte ich 2025 in Access verwenden?
Kurze Antwort: DAO.
Lange Antwort: Kommt drauf an.
Verwende DAO, wenn:
- Du hauptsächlich mit Access-Datenbanken (.accdb, .mdb) arbeitest
- Du komplexe Abfragen mit Jet-SQL brauchst
- Du Recordsets bearbeiten willst (AddNew, Edit, Update)
- Du TableDefs, QueryDefs oder Relations nutzt
- Performance bei lokalen Datenbanken wichtig ist
Verwende ADO, wenn:
- Du auf SQL Server, Oracle oder andere externe Datenbanken zugreifst
- Du Stored Procedures mit Output-Parametern brauchst
- Du asynchrone Operationen fahren willst
- Du mit XML-Daten arbeitest
- Du auf moderne Features wie Connection Pooling angewiesen bist
Microsoft’s Position:
DAO ist für Access empfohlen. ADO ist legacy, aber nicht deprecated.
Warum ist DAO schneller bei Access-Datenbanken?
DAO spricht direkt mit der ACE/Jet-Engine.
ADO geht über OLE DB Provider. Das ist eine zusätzliche Schicht.
Performance-Vergleich (empirisch):
| Operation | DAO (ms) | ADO (ms) | Unterschied |
|---|---|---|---|
| 10.000 Datensätze lesen | 250 | 380 | +52% |
| 1.000 Datensätze einfügen | 180 | 290 | +61% |
| Komplexe JOIN-Abfrage | 120 | 195 | +63% |
| Recordset öffnen/schließen | 15 | 28 | +87% |
Grund: DAO hat direkten Speicherzugriff auf Jet/ACE-Strukturen.
ADO muss über COM-Marshalling, OLE DB Provider und dann erst zur Engine.
Beispiel: Recordset öffnen (DAO):
Public Sub ReadWithDAO()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim startTime As Double
startTime = Timer
Set db = CurrentDb()
Set rs = db.OpenRecordset("SELECT * FROM Kunden", dbOpenSnapshot)
Do While Not rs.EOF
' Verarbeitung
Debug.Print rs!KundenID
rs.MoveNext
Loop
rs.Close
Set rs = Nothing
Set db = Nothing
Debug.Print "DAO Zeit: " & (Timer - startTime) & " Sekunden"
End Sub
Beispiel: Recordset öffnen (ADO):
Public Sub ReadWithADO()
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim startTime As Double
startTime = Timer
Set cn = New ADODB.Connection
cn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & CurrentProject.FullName
Set rs = New ADODB.Recordset
rs.Open "SELECT * FROM Kunden", cn, adOpenStatic, adLockReadOnly
Do While Not rs.EOF
' Verarbeitung
Debug.Print rs("KundenID").Value
rs.MoveNext
Loop
rs.Close
cn.Close
Set rs = Nothing
Set cn = Nothing
Debug.Print "ADO Zeit: " & (Timer - startTime) & " Sekunden"
End Sub
Ergebnis: DAO ist ca. 40-60% schneller bei gleichem Datenvolumen.
Welche Recordset-Typen gibt es und welche soll ich verwenden?
Hier wird’s technisch.
DAO Recordset-Typen:
dbOpenTable:
Nur für lokale Tabellen. Direkter Tabellenzugriff.
Unterstützt Seek (schnellste Suchfunktion).
Set rs = db.OpenRecordset("Kunden", dbOpenTable)
rs.Index = "PrimaryKey"
rs.Seek "=", 12345
If Not rs.NoMatch Then
Debug.Print rs!Name
End If
dbOpenDynaset:
Für Abfragen und verknüpfte Tabellen.
Datensätze sind editierbar.
Zeigt nur Key-Cursor, lädt Daten bei Bedarf.
Set rs = db.OpenRecordset("SELECT * FROM Kunden WHERE Stadt = 'Hamburg'", dbOpenDynaset)
If Not rs.EOF Then
rs.Edit
rs!Status = "Aktiv"
rs.Update
End If
dbOpenSnapshot:
Read-Only Recordset.
Statische Kopie der Daten.
Schneller als Dynaset, wenn du nur lesen willst.
Set rs = db.OpenRecordset("SELECT * FROM Bestellungen", dbOpenSnapshot)
' Keine Änderungen möglich
dbOpenForwardOnly:
Schnellster Typ. Nur vorwärts scrollen.
Keine Änderungen, kein RecordCount.
Set rs = db.OpenRecordset("SELECT * FROM Protokoll", dbOpenForwardOnly)
Do While Not rs.EOF
Debug.Print rs!Meldung
rs.MoveNext
Loop
ADO Recordset-Typen:
adOpenForwardOnly:
Standard. Nur vorwärts. Wie DAO dbOpenForwardOnly.
adOpenStatic:
Statischer Snapshot. Wie DAO dbOpenSnapshot.
adOpenDynamic:
Zeigt Änderungen von anderen Usern live.
adOpenKeyset:
Wie Dynaset. Keys werden gecacht.
Performance-Empfehlung:
| Use Case | DAO | ADO |
|---|---|---|
| Große Menge lesen (read-only) | dbOpenForwardOnly | adOpenForwardOnly |
| Daten bearbeiten | dbOpenDynaset | adOpenKeyset |
| Einzelne Datensätze suchen | dbOpenTable + Seek | adOpenKeyset + Find |
| Reporting/Export | dbOpenSnapshot | adOpenStatic |
Wie arbeite ich mit Transaktionen?
Transaktionen sind kritisch für Datenintegrität.
DAO Transaktionen:
Public Sub DAOTransaction()
On Error GoTo ErrorHandler
Dim db As DAO.Database
Dim rs As DAO.Recordset
Set db = CurrentDb()
' Transaktion starten
db.BeginTrans
' Operation 1: Bestellung anlegen
Set rs = db.OpenRecordset("Bestellungen", dbOpenDynaset)
rs.AddNew
rs!KundenID = 12345
rs!Datum = Date
rs!Betrag = 1500.50
rs.Update
Dim lngBestellID As Long
lngBestellID = rs!BestellID
rs.Close
' Operation 2: Positionen einfügen
Set rs = db.OpenRecordset("Bestellpositionen", dbOpenDynaset)
rs.AddNew
rs!BestellID = lngBestellID
rs!ArtikelID = 789
rs!Menge = 5
rs.Update
rs.Close
' Transaktion committen
db.CommitTrans
Set rs = Nothing
Set db = Nothing
Exit Sub
ErrorHandler:
' Rollback bei Fehler
db.Rollback
Debug.Print "Transaktion rückgängig gemacht: " & Err.Description
End Sub
ADO Transaktionen:
Public Sub ADOTransaction()
On Error GoTo ErrorHandler
Dim cn As ADODB.Connection
Dim cmd As ADODB.Command
Set cn = New ADODB.Connection
cn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & CurrentProject.FullName
' Transaktion starten
cn.BeginTrans
' Operation 1
Set cmd = New ADODB.Command
cmd.ActiveConnection = cn
cmd.CommandText = "INSERT INTO Bestellungen (KundenID, Datum, Betrag) VALUES (?, ?, ?)"
cmd.Parameters.Append cmd.CreateParameter("KundenID", adInteger, adParamInput, , 12345)
cmd.Parameters.Append cmd.CreateParameter("Datum", adDate, adParamInput, , Date)
cmd.Parameters.Append cmd.CreateParameter("Betrag", adCurrency, adParamInput, , 1500.50)
cmd.Execute
' BestellID abrufen
Dim rs As ADODB.Recordset
Set rs = cn.Execute("SELECT @@IDENTITY AS LastID")
Dim lngBestellID As Long
lngBestellID = rs("LastID").Value
rs.Close
' Operation 2
Set cmd = New ADODB.Command
cmd.ActiveConnection = cn
cmd.CommandText = "INSERT INTO Bestellpositionen (BestellID, ArtikelID, Menge) VALUES (?, ?, ?)"
cmd.Parameters.Append cmd.CreateParameter("BestellID", adInteger, adParamInput, , lngBestellID)
cmd.Parameters.Append cmd.CreateParameter("ArtikelID", adInteger, adParamInput, , 789)
cmd.Parameters.Append cmd.CreateParameter("Menge", adInteger, adParamInput, , 5)
cmd.Execute
' Commit
cn.CommitTrans
cn.Close
Set cmd = Nothing
Set cn = Nothing
Exit Sub
ErrorHandler:
cn.RollbackTrans
Debug.Print "Rollback: " & Err.Description
End Sub
Wichtig: Access/Jet unterstützt keine verschachtelten Transaktionen.
BeginTrans → CommitTrans oder Rollback. Fertig.
Wie nutze ich parametrisierte Abfragen?
SQL-Injection vermeiden. Immer.
DAO mit QueryDef:
Public Function GetKundeByID(lngKundenID As Long) As DAO.Recordset
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Dim rs As DAO.Recordset
Set db = CurrentDb()
' QueryDef erstellen (temporär)
Set qdf = db.CreateQueryDef("", _
"PARAMETERS pKundenID Long; " & _
"SELECT * FROM Kunden WHERE KundenID = [pKundenID]")
' Parameter setzen
qdf.Parameters("pKundenID") = lngKundenID
' Recordset öffnen
Set rs = qdf.OpenRecordset(dbOpenSnapshot)
Set GetKundeByID = rs
' qdf wird automatisch freigegeben (temporär)
End Function
DAO mit gespeicherter Query:
' Voraussetzung: Gespeicherte Query "qryKundeByID" mit Parameter [pKundenID]
Public Function GetKundeViaStoredQuery(lngKundenID As Long) As DAO.Recordset
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Set db = CurrentDb()
Set qdf = db.QueryDefs("qryKundeByID")
qdf.Parameters("pKundenID") = lngKundenID
Set GetKundeViaStoredQuery = qdf.OpenRecordset(dbOpenSnapshot)
End Function
ADO mit Command-Object:
Public Function GetKundeADO(lngKundenID As Long) As ADODB.Recordset
Dim cn As ADODB.Connection
Dim cmd As ADODB.Command
Dim rs As ADODB.Recordset
Set cn = New ADODB.Connection
cn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & CurrentProject.FullName
Set cmd = New ADODB.Command
cmd.ActiveConnection = cn
cmd.CommandText = "SELECT * FROM Kunden WHERE KundenID = ?"
cmd.CommandType = adCmdText
' Parameter hinzufügen
cmd.Parameters.Append cmd.CreateParameter("KundenID", adInteger, adParamInput, , lngKundenID)
Set rs = cmd.Execute
Set GetKundeADO = rs
' Connection bleibt offen - muss vom Caller geschlossen werden
End Function
Wichtig bei ADO: Fragezeichen (?) als Platzhalter. Nicht Named Parameters wie bei DAO.
Wenn du Named Parameters willst:
cmd.CommandText = "SELECT * FROM Kunden WHERE KundenID = @KundenID"
cmd.Parameters.Append cmd.CreateParameter("@KundenID", adInteger, adParamInput, , lngKundenID)
Aber Achtung: Funktioniert nur mit SQL Server, nicht mit Access/ACE.
Wie verbinde ich mich mit SQL Server?
DAO kann das. ADO ist aber besser dafür.
DAO zu SQL Server (über ODBC):
Public Sub DAOtoSQLServer()
Dim db As DAO.Database
Dim rs As DAO.Recordset
' ODBC-Verbindung
Set db = OpenDatabase("", False, False, _
"ODBC;DRIVER={ODBC Driver 17 for SQL Server};" & _
"SERVER=DEIN_SERVER;DATABASE=DEINE_DB;Trusted_Connection=Yes;")
Set rs = db.OpenRecordset("SELECT * FROM Kunden", dbOpenSnapshot)
Do While Not rs.EOF
Debug.Print rs!Name
rs.MoveNext
Loop
rs.Close
db.Close
Set rs = Nothing
Set db = Nothing
End Sub
Problem: DAO über ODBC ist langsam. Nicht empfohlen für SQL Server.
ADO zu SQL Server (nativ):
Public Sub ADOtoSQLServer()
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Set cn = New ADODB.Connection
' Native SQL Server Verbindung
cn.ConnectionString = _
"Provider=SQLOLEDB;" & _
"Data Source=DEIN_SERVER;" & _
"Initial Catalog=DEINE_DB;" & _
"Integrated Security=SSPI;"
cn.Open
Set rs = New ADODB.Recordset
rs.Open "SELECT * FROM Kunden", cn, adOpenStatic, adLockReadOnly
Do While Not rs.EOF
Debug.Print rs("Name").Value
rs.MoveNext
Loop
rs.Close
cn.Close
Set rs = Nothing
Set cn = Nothing
End Sub
ADO mit Stored Procedure:
Public Sub CallStoredProcedure()
Dim cn As ADODB.Connection
Dim cmd As ADODB.Command
Dim rs As ADODB.Recordset
Set cn = New ADODB.Connection
cn.Open "Provider=SQLOLEDB;Data Source=SERVER;Initial Catalog=DB;Integrated Security=SSPI;"
Set cmd = New ADODB.Command
cmd.ActiveConnection = cn
cmd.CommandText = "dbo.GetKundenByStadt"
cmd.CommandType = adCmdStoredProc
' Input Parameter
cmd.Parameters.Append cmd.CreateParameter("@Stadt", adVarChar, adParamInput, 50, "Hamburg")
' Output Parameter
cmd.Parameters.Append cmd.CreateParameter("@AnzahlKunden", adInteger, adParamOutput)
Set rs = cmd.Execute
Do While Not rs.EOF
Debug.Print rs("KundenID").Value & " - " & rs("Name").Value
rs.MoveNext
Loop
' Output Parameter auslesen
Debug.Print "Anzahl Kunden: " & cmd.Parameters("@AnzahlKunden").Value
rs.Close
cn.Close
End Sub
SQL Server: Beispiel Stored Procedure
CREATE PROCEDURE dbo.GetKundenByStadt
@Stadt NVARCHAR(50),
@AnzahlKunden INT OUTPUT
AS
BEGIN
SET NOCOUNT ON;
SELECT
KundenID,
Name,
Stadt,
Email
FROM dbo.Kunden
WHERE Stadt = @Stadt
ORDER BY Name;
SET @AnzahlKunden = @@ROWCOUNT;
END;
Wie handhabe ich Recordset-Updates effizient?
Einzelne Updates sind langsam. Batch-Updates sind schnell.
DAO: Ineffizient (einzelne Updates):
Public Sub SlowUpdate()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Set db = CurrentDb()
Set rs = db.OpenRecordset("Kunden", dbOpenDynaset)
Do While Not rs.EOF
If rs!Status = "Inaktiv" Then
rs.Edit
rs!LetztePruefung = Date
rs.Update
End If
rs.MoveNext
Loop
rs.Close
Set rs = Nothing
Set db = Nothing
End Sub
Problem: Jedes Update schreibt sofort. Bei 10.000 Datensätzen = 10.000 Schreibvorgänge.
DAO: Effizient (SQL UPDATE):
Public Sub FastUpdate()
Dim db As DAO.Database
Set db = CurrentDb()
db.Execute _
"UPDATE Kunden SET LetztePruefung = Date() WHERE Status = 'Inaktiv'", _
dbFailOnError
Debug.Print "Datensätze aktualisiert: " & db.RecordsAffected
Set db = Nothing
End Sub
Vorteil: Ein Statement. Jet/ACE optimiert intern. 100x schneller.
ADO: Batch-Update mit Recordset:
Public Sub ADOBatchUpdate()
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Set cn = New ADODB.Connection
cn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & CurrentProject.FullName
Set rs = New ADODB.Recordset
rs.CursorLocation = adUseClient
rs.LockType = adLockBatchOptimistic
rs.Open "SELECT * FROM Kunden WHERE Status = 'Inaktiv'", cn
Do While Not rs.EOF
rs("LetztePruefung").Value = Date
rs.MoveNext
Loop
' Alle Änderungen auf einmal schreiben
rs.UpdateBatch
rs.Close
cn.Close
Set rs = Nothing
Set cn = Nothing
End Sub
Vorteil: Änderungen werden gecacht und in einem Batch geschrieben.
SQL Server: Bulk Update mit Temp Table
-- Temporäre Tabelle mit Updates
CREATE TABLE #Updates (
KundenID INT PRIMARY KEY,
NeuerStatus NVARCHAR(50),
LetzteAenderung DATETIME2
);
-- Daten einfügen (z.B. aus Access via ADO)
INSERT INTO #Updates (KundenID, NeuerStatus, LetzteAenderung)
VALUES
(1, 'Aktiv', GETDATE()),
(2, 'Inaktiv', GETDATE()),
(3, 'Aktiv', GETDATE());
-- ... tausende Zeilen
-- Bulk Update
UPDATE k
SET
k.Status = u.NeuerStatus,
k.LetzteAenderung = u.LetzteAenderung
FROM dbo.Kunden k
INNER JOIN #Updates u ON k.KundenID = u.KundenID;
DROP TABLE #Updates;
Aus Access heraus aufrufen:
Public Sub BulkUpdateViaSQL()
Dim cn As ADODB.Connection
Dim cmd As ADODB.Command
Set cn = New ADODB.Connection
cn.Open "Provider=SQLOLEDB;Data Source=SERVER;Initial Catalog=DB;Integrated Security=SSPI;"
Set cmd = New ADODB.Command
cmd.ActiveConnection = cn
cmd.CommandTimeout = 300 ' 5 Minuten
' Temp Table erstellen
cmd.CommandText = "CREATE TABLE #Updates (KundenID INT, NeuerStatus NVARCHAR(50))"
cmd.Execute
' Daten einfügen (vereinfacht, in Produktion via Loop oder Array)
cmd.CommandText = "INSERT INTO #Updates VALUES (1, 'Aktiv'), (2, 'Inaktiv')"
cmd.Execute
' Bulk Update
cmd.CommandText = _
"UPDATE k SET k.Status = u.NeuerStatus " & _
"FROM dbo.Kunden k INNER JOIN #Updates u ON k.KundenID = u.KundenID"
cmd.Execute
Debug.Print "Rows affected: " & cmd.Parameters(0).Value
cn.Close
Set cmd = Nothing
Set cn = Nothing
End Sub
Wie gehe ich mit Memo-Feldern und BLOB-Daten um?
Große Datenfelder brauchen besondere Behandlung.
DAO: Memo-Feld lesen/schreiben:
Public Sub DAOMemoField()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Set db = CurrentDb()
Set rs = db.OpenRecordset("Artikel", dbOpenDynaset)
If Not rs.EOF Then
rs.Edit
' Memo-Feld (Long Text in Access)
rs!Beschreibung = String(50000, "A") ' 50.000 Zeichen
rs.Update
End If
rs.Close
Set rs = Nothing
Set db = Nothing
End Sub
DAO: OLE Object (BLOB) schreiben:
Public Sub DAOInsertBLOB()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim fld As DAO.Field
Set db = CurrentDb()
Set rs = db.OpenRecordset("Dokumente", dbOpenDynaset)
rs.AddNew
rs!DokumentName = "Rechnung.pdf"
Set fld = rs!DokumentDaten ' OLE Object Feld
' Datei als Binärdaten einlesen
Dim strFilePath As String
strFilePath = "C:\Dokumente\Rechnung.pdf"
' LoadFromFile ist nicht direkt verfügbar in DAO
' Workaround: Über ADO Stream oder FSO
' Hier vereinfacht:
fld.LoadFromFile strFilePath
rs.Update
rs.Close
Set rs = Nothing
Set db = Nothing
End Sub
Problem: DAO hat keine native LoadFromFile-Methode für OLE Object.
ADO: BLOB mit Stream-Object:
Public Sub ADOInsertBLOB()
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim stm As ADODB.Stream
Set cn = New ADODB.Connection
cn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & CurrentProject.FullName
Set rs = New ADODB.Recordset
rs.Open "Dokumente", cn, adOpenKeyset, adLockOptimistic
rs.AddNew
rs("DokumentName").Value = "Rechnung.pdf"
' Stream-Object für Binärdaten
Set stm = New ADODB.Stream
stm.Type = adTypeBinary
stm.Open
stm.LoadFromFile "C:\Dokumente\Rechnung.pdf"
rs("DokumentDaten").Value = stm.Read
rs.Update
stm.Close
rs.Close
cn.Close
Set stm = Nothing
Set rs = Nothing
Set cn = Nothing
End Sub
ADO: BLOB lesen und speichern:
Public Sub ADOExtractBLOB()
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim stm As ADODB.Stream
Set cn = New ADODB.Connection
cn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & CurrentProject.FullName
Set rs = New ADODB.Recordset
rs.Open "SELECT * FROM Dokumente WHERE DokumentID = 1", cn
If Not rs.EOF Then
Set stm = New ADODB.Stream
stm.Type = adTypeBinary
stm.Open
stm.Write rs("DokumentDaten").Value
stm.SaveToFile "C:\Export\Rechnung_Export.pdf", adSaveCreateOverWrite
stm.Close
End If
rs.Close
cn.Close
Set stm = Nothing
Set rs = Nothing
Set cn = Nothing
End Sub
Vorteil ADO: Stream-Object macht BLOB-Handling einfacher.
Wie optimiere ich Performance bei großen Datenmengen?
10.000 Datensätze sind kein Problem. 1 Million schon.
DAO: Indexe nutzen (Seek):
Public Sub DAOSeek()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Set db = CurrentDb()
Set rs = db.OpenRecordset("Kunden", dbOpenTable)
' Index festlegen
rs.Index = "PrimaryKey"
' Seek = schnellste Suchmethode in DAO
rs.Seek "=", 12345
If Not rs.NoMatch Then
Debug.Print rs!Name
Else
Debug.Print "Nicht gefunden"
End If
rs.Close
Set rs = Nothing
Set db = Nothing
End Sub
Wichtig: Seek funktioniert nur mit dbOpenTable. Nicht mit Queries.
DAO: FindFirst (langsamer, aber flexibler):
Public Sub DAOFindFirst()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Set db = CurrentDb()
Set rs = db.OpenRecordset("SELECT * FROM Kunden", dbOpenDynaset)
rs.FindFirst "Stadt = 'Hamburg'"
If Not rs.NoMatch Then
Debug.Print rs!Name
End If
rs.Close
Set rs = Nothing
Set db = Nothing
End Sub
ADO: Find-Methode:
Public Sub ADOFind()
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Set cn = New ADODB.Connection
cn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & CurrentProject.FullName
Set rs = New ADODB.Recordset
rs.Open "SELECT * FROM Kunden", cn, adOpenKeyset, adLockReadOnly
rs.Find "Stadt = 'Hamburg'"
If Not rs.EOF Then
Debug.Print rs("Name").Value
End If
rs.Close
cn.Close
Set rs = Nothing
Set cn = Nothing
End Sub
Performance-Tipps:
1. Verwende WHERE-Klauseln, nicht Recordset-Filter:
' Langsam
Set rs = db.OpenRecordset("Kunden", dbOpenDynaset)
rs.Filter = "Stadt = 'Hamburg'"
Set rsFiltered = rs.OpenRecordset()
' Schnell
Set rs = db.OpenRecordset("SELECT * FROM Kunden WHERE Stadt = 'Hamburg'", dbOpenSnapshot)
2. Nutze Indizes für WHERE-Klauseln:
-- In Access: Index auf Stadt-Feld anlegen
CREATE INDEX idx_Stadt ON Kunden(Stadt);
3. Verwende dbOpenForwardOnly für große Datenmengen:
Set rs = db.OpenRecordset("SELECT * FROM Protokoll", dbOpenForwardOnly)
' 3-5x schneller als dbOpenDynaset
4. Limitiere Spalten (SELECT nur was du brauchst):
' Langsam
Set rs = db.OpenRecordset("SELECT * FROM Kunden")
' Schnell
Set rs = db.OpenRecordset("SELECT KundenID, Name FROM Kunden")
Wie migriere ich von DAO zu ADO (oder umgekehrt)?
Migration ist machbar. Aber nicht trivial.
Typische DAO → ADO Migration:
DAO-Code (alt):
Dim db As DAO.Database
Dim rs As DAO.Recordset
Set db = CurrentDb()
Set rs = db.OpenRecordset("Kunden", dbOpenDynaset)
Do While Not rs.EOF
Debug.Print rs!Name
rs.MoveNext
Loop
rs.Close
Set rs = Nothing
Set db = Nothing
ADO-Code (neu):
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Set cn = New ADODB.Connection
cn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & CurrentProject.FullName
Set rs = New ADODB.Recordset
rs.Open "Kunden", cn, adOpenKeyset, adLockOptimistic
Do While Not rs.EOF
Debug.Print rs("Name").Value
rs.MoveNext
Loop
rs.Close
cn.Close
Set rs = Nothing
Set cn = Nothing
Mapping-Tabelle:
| DAO | ADO |
|---|---|
| Database | Connection |
| OpenRecordset | Recordset.Open |
| dbOpenDynaset | adOpenKeyset |
| dbOpenSnapshot | adOpenStatic |
| dbOpenForwardOnly | adOpenForwardOnly |
| rs!Feldname | rs(„Feldname“).Value |
| AddNew/Edit/Update | AddNew/Update |
| Seek | Find |
| NoMatch | EOF/BOF |
| RecordCount | RecordCount |
ADO → DAO Migration (seltener):
Meist nur, wenn du von SQL Server zurück zu Access gehst.
Oder wenn Performance-Probleme mit ADO auftreten.
Vorsicht: ADO-Features wie asynchrone Abfragen gibt’s in DAO nicht.
Mein Fazit aus 20 Jahren Access-Entwicklung
Ich hab beides durch. Zig Projekte. Tausende Zeilen Code.
Meine Empfehlung:
- Access-Backend: DAO
- SQL Server-Backend: ADO
- Hybrid (Access + SQL Server): Beide, je nach Kontext
DAO ist nicht tot. Microsoft pflegt es weiter. Access 2019/2021/365 läuft stabil damit.
ADO ist nicht deprecated. Nur „nicht mehr die Zukunft“. Funktioniert aber.
Was zählt: Kenne beide. Nutze die richtige für den Job.
Fragen? Schreib mir.
Ich bin der Datenschäfer. Und ich entwickle Access-Lösungen seit 1999.