{"id":55000446,"date":"2024-12-01T00:00:00","date_gmt":"2025-06-23T16:49:46","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=446"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"ADODB_Connections_und_Connectionstrings","status":"publish","type":"post","link":"https:\/\/vbentwickler.de\/ADODB_Connections_und_Connectionstrings\/","title":{"rendered":"ADODB: Connections und Connectionstrings"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg08.met.vgwort.de\/na\/93025ae925c646299b0a8616384601c7\" width=\"1\" height=\"1\" alt=\"\"><b>Wer auf die Inhalte von Datenbanken wie Access, SQL Server und anderen zugreifen m&ouml;chte, ben&ouml;tigt eine spezielle Datenzugriffstechnologie. Unter VB6, VBA und twinBASIC verwendet man dazu in der Regel die DAO-Bibliothek, in Office &#8220;Microsoft Office 16.0 Access database engine Object Library&#8221; genannt, oder die ADODB-Bibliothek (&#8220;Microsoft ActiveX Data Objects 6.1 Library&#8221;). Geschichtlich wurde mal die eine, mal die andere von Microsoft als die zu bevorzugende Datenzugriffstechnik bezeichnet. Derzeit verwendet man meist DAO, vor allem in Verbindung mit Access-Datenbanken, aber beim Zugriff auf SQL Server-Datenbanken bietet ADODB einige Features, die wir mit DAO nicht nutzen k&ouml;nnen. In diesem Artikel steigen wir in die Programmierung von Datenbankzugriffen mit ADODB ein. Dabei schauen wir uns als Erstes die Connection-Klasse an, mit der erst einmal eine Verbindung zur Datenbank aufgebaut werden kann.<\/b><\/p>\n<p>ADODB wurde mit der Version Access 2000 erstmalig eingef&uuml;hrt. Zuvor war DAO die meistverwendete Datenzugriffstechnik (Bibliothek <b>Microsoft DAO 3.6 Object Library<\/b>) in Zusammenhang mit dem Zugriff &uuml;ber die JET-Datenbank-Engine. Im Laufe der Jahre hat Microsoft jedoch entschieden, dass DAO wieder die wichtigste Technik f&uuml;r den Zugriff auf Datenbanken sein soll. Damit einher ging mit Access 2007 die Einf&uuml;hrung einer neuen Variante der <b>JET<\/b>-Engine namens <b>ACE <\/b>(Access Database Engine) und damit eine neue Bibliothek mit dem Titel <b>Microsoft Office 16.0 Access database engine Object Library<\/b>.<\/p>\n<p>Wie bereits erw&auml;hnt, gibt es jedoch einige Einsatzzwecke, bei denen ADODB  Vorteile gegen&uuml;ber DAO hat, weil es verschiedene Funktionen zur Verf&uuml;gung stellt, die es in DAO nicht gibt. Dazu geh&ouml;ren die folgenden:<\/p>\n<ul>\n<li><b>Bessere Unterst&uuml;tzung f&uuml;r SQL Server<\/b>: ADODB ist f&uuml;r client-server-basierte Datenbanken wie SQL Server optimiert. DAO ist prim&auml;r f&uuml;r Microsoft Access und Jet-Datenbanken konzipiert und weniger effizient bei der Arbeit mit SQL Server.<\/li>\n<li><b>Unterst&uuml;tzung f&uuml;r OLE DB<\/b>: ADODB verwendet OLE DB oder ODBC, um sich mit SQL Server zu verbinden, was eine performante und flexible Verbindung erm&ouml;glicht. DAO ist auf die Jet-Engine beschr&auml;nkt, die f&uuml;r SQL Server nicht optimiert ist. Mit DAO k&ouml;nnen wir nur in direkt &uuml;ber Tabellenverkn&uuml;pfungen oder Pass-Through-Abfragen auf SQL Server-Tabellen zugreifen.<\/li>\n<li><b>Bessere Performance bei gro&szlig;en Datenmengen<\/b>: ADODB kann gro&szlig;e Datenmengen effizient &uuml;ber serverseitige Cursor oder Forward-Only-Recordsets abrufen. DAO l&auml;dt oft ganze Datensatzgruppen in den Speicher, was zu Performance-Problemen f&uuml;hrt.<\/li>\n<li><b>Mehr Flexibilit&auml;t bei der Abfrageverarbeitung<\/b>:ADODB erlaubt den direkten Aufruf von gespeicherten Prozeduren und somit parametrisierten Abfragen, was die Sicherheit und Performance erh&ouml;ht. DAO unterst&uuml;tzt keine direkten Prozeduraufrufe in SQL Server.<\/li>\n<li><b>Transaktionsunterst&uuml;tzung f&uuml;r SQL Server<\/b>: ADODB bietet eine bessere Transaktionskontrolle mit <b>BeginTrans<\/b>, <b>CommitTrans <\/b>und <b>RollbackTrans<\/b>. DAO bietet zwar Transaktionsunterst&uuml;tzung, aber diese ist f&uuml;r Jet-Datenbanken optimiert und nicht f&uuml;r SQL Server.<\/li>\n<\/ul>\n<h2>Early oder Late binding<\/h2>\n<p>Wir k&ouml;nnen die Elemente der ADODB-Bibliothek auf verschiedene Arten nutzen &#8211; durch vorheriges Einbinden der Bibliothek (Early Binding) oder durch Deklarieren der Objektvariablen mit dem Datentyp Object und Einbinden zur Laufzeit (Late Binding).<\/p>\n<p>Wir wollen wegen der damit verbundenen Vorteile zum Beispiel durch den Einsatz von IntelliSense hier mit Early Binding arbeiten.<\/p>\n<p>Dazu ben&ouml;tigen wir einen Verweis auf die Bibliothek <b>Microsoft ActiveX Data Objects 6.1 Library<\/b>.<\/p>\n<p>Diesen f&uuml;gen wir wie in Bild 1 &uuml;ber den <b>Verweise<\/b>-Dialog hinzu.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_06\/pic_446_001.png\" alt=\"Verweis auf die ADODB-Bibliothek\" width=\"549,6265\" height=\"433,291\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Verweis auf die ADODB-Bibliothek<\/span><\/b><\/p>\n<h2>Eigenschaften der Connection-Klasse<\/h2>\n<p>Die <b>Connection<\/b>-Klasse liefert die folgenden Eigenschaften, von denen wir uns die wichtigsten in den folgenden Abschnitten ansehen:<\/p>\n<ul>\n<li><b>Attributes<\/b>: Bestimmt oder setzt verschiedene Verbindungsattribute. Wird selten verwendet.<\/li>\n<li><b>CommandTimeout<\/b>: Legt fest, wie lange (in Sekunden) eine Abfrage auf eine Antwort warten soll, bevor ein Timeout-Fehler auftritt.<\/li>\n<li><b>ConnectionString<\/b>: Enth&auml;lt die Verbindungsinformationen zur Datenbank (zum Beispiel Servername, Datenbankname, Benutzer, Passwort).<\/li>\n<li><b>ConnectionTimeout<\/b>: Gibt die maximale Zeit (in Sekunden) an, die beim Verbindungsaufbau auf eine Antwort gewartet wird, bevor ein Timeout-Fehler auftritt.<\/li>\n<li><b>CursorLocation<\/b>: Bestimmt, ob die Cursor-Verarbeitung clientseitig oder serverseitig erfolgt (<b>adUseClient <\/b>oder <b>adUseServer<\/b>).<\/li>\n<li><b>DefaultDatabase<\/b>: Gibt die Standard-Datenbank an, die nach dem &Ouml;ffnen der Verbindung verwendet wird.<\/li>\n<li><b>Errors<\/b>: Liefert eine Sammlung von Fehlern, die w&auml;hrend der letzten ADODB-Operation aufgetreten sind.<\/li>\n<li><b>IsolationLevel<\/b>: Gibt das Isolationsniveau f&uuml;r Transaktionen an (zum Beispiel <b>ReadCommitted<\/b>, <b>Serializable<\/b>).<\/li>\n<li><b>Mode<\/b>: Bestimmt die Art des Datenbankzugriffs (zum Beispiel <b>Nur-Lesen<\/b>, <b>Schreibgesch&uuml;tzt<\/b>, <b>Exklusiv<\/b>).<\/li>\n<li><b>Properties<\/b>: Eine Sammlung aller Eigenschaften des <b>Connection<\/b>-Objekts.<\/li>\n<li><b>Provider<\/b>: Gibt den verwendeten OLE DB-Provider an (zum Beispiel <b>SQLOLEDB<\/b> f&uuml;r SQL Server).<\/li>\n<li><b>State<\/b>: Gibt den aktuellen Status der Verbindung zur&uuml;ck (zum Beispiel <b>adStateOpen <\/b>oder <b>adStateClosed<\/b>).<\/li>\n<li><b>Version<\/b>: Gibt die Version von ADO zur&uuml;ck.<\/li>\n<\/ul>\n<h2>Methoden der Connection-Klasse<\/h2>\n<p>Au&szlig;erdem bietet die <b>Connection<\/b>-Klasse die folgenden Methoden:<\/p>\n<ul>\n<li><b>BeginTrans<\/b>: Startet eine Transaktion, um mehrere Operationen als Einheit auszuf&uuml;hren.<\/li>\n<li><b>Cancel<\/b>: Bricht eine laufende Abfrage oder Operation ab.<\/li>\n<li><b>Close<\/b>: Schlie&szlig;t die Verbindung zur Datenbank.<\/li>\n<li><b>CommitTrans<\/b>: Best&auml;tigt eine laufende Transaktion und speichert die &Auml;nderungen dauerhaft in der Datenbank.<\/li>\n<li><b>Execute<\/b>: F&uuml;hrt eine SQL-Abfrage aus und gibt ein Recordset oder die Anzahl der betroffenen Datens&auml;tze zur&uuml;ck.<\/li>\n<li><b>Open<\/b>: Stellt eine Verbindung zur Datenbank mit den angegebenen Verbindungsparametern her.<\/li>\n<li><b>OpenSchema<\/b>: Ruft Metadaten &uuml;ber die Datenbank ab (zum Beispiel Tabellen, Spalten, Indexe).<\/li>\n<li><b>RollbackTrans<\/b>: Bricht eine Transaktion ab und stellt die Daten vor der Transaktion wieder her.<\/li>\n<\/ul>\n<h2>Zugriff auf die aktuelle Access-Datenbank<\/h2>\n<p>Innerhalb von Access-Datenbanken liefert die ADODB-Bibliothek &uuml;ber die Eigenschaft <b>Connection <\/b>der Klasse <b>CurrentProject <\/b>ein <b>Connection<\/b>-Objekt f&uuml;r den Zugriff auf die aktuelle Datenbank.<\/p>\n<p>Um diese zu nutzen, k&ouml;nnen wir direkt auf ihre Eigenschaften zugreifen &#8211; beispielsweise, indem wir die Verbindungszeichenfolge im Direktbereich ausgeben:<\/p>\n<pre>  CurrentProject.Connection.ConnectionString\r\nProvider=Microsoft.ACE.OLEDB.12.0;User ID=Admin;Data Source=C:\\...\\ADODB_Connections.accdb;Mode=Share Deny None;Extended Properties=\"\";Jet OLEDB:System database=C:\\Users\\User\\AppData\\Roaming\\Microsoft\\Access\\System.mdw;Jet OLEDB:Registry Path=Software\\Microsoft\\Office\\16.0\\Access\\Access Connectivity Engine;Jet OLEDB:Database Password=\"\";Jet OLEDB:Engine Type=6;Jet OLEDB:Database Locking Mode=0;Jet OLEDB:Global Partial Bulk Ops=2;Jet OLEDB:Global Bulk Transactions=1;Jet OLEDB:<span style=\"color:blue;\">New<\/span> Database Password=\"\";Jet OLEDB:Create System Database=False;Jet OLEDB:Encrypt Database=False;Jet OLEDB:Don''t Copy Locale on Compact=False;Jet OLEDB:Compact Without Replica Repair=False;Jet OLEDB:SFP=False;Jet OLEDB:Support Complex Data=True;Jet OLEDB:Bypass UserInfo Validation=False;Jet OLEDB:Limited DB Caching=False;Jet OLEDB:Bypass ChoiceField Validation=<span style=\"color:blue;\">False<\/span><\/pre>\n<p>Hier finden wir eine ganze Reihe Eigenschaften, die jedoch nicht alle immer ben&ouml;tigt werden.<\/p>\n<p>Wir k&ouml;nnen die Verbindung auch direkt in Form einer <b>Connection<\/b>-Variablen speichern und dar&uuml;ber auf die enthaltenen Eigenschaften zugreifen:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>AktiveDatenbank()\r\n     <span style=\"color:blue;\">Dim <\/span>cnn<span style=\"color:blue;\"> As <\/span>ADODB.Connection\r\n     <span style=\"color:blue;\">Set<\/span> cnn = CurrentProject.Connection\r\n     <span style=\"color:blue;\">Debug.Print<\/span> cnn.ConnectionString\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Zu diesem Zeitpunkt haben wir &uuml;brigens noch keine Verbindung zur Datenbank hergestellt. Das <b>Connection<\/b>-Objekt kennt erst einmal nur die Verbindungszeichenfolge. Wie wir die Verbindung herstellen, schauen wir uns weiter unten an.<\/p>\n<h2>Verbindungszeichenfolgen f&uuml;r den Zugriff per ADODB<\/h2>\n<p>Dies war der stark vereinfachte Fall f&uuml;r den Zugriff auf die aktuelle Access-Datenbank. ADODB nutzt man jedoch in der Regel eher dazu, auf Datenquellen au&szlig;erhalb der aktuellen Anwendung zuzugreifen. Wir schauen uns verschiedene Beispiele an, die oft verwendet werden.<\/p>\n<p>Die Seite <b>https:\/\/www.connectionstrings.com\/<\/b> stellt immer aktuelle Informationen rund um die Verbindungszeichenfolgen f&uuml;r den Zugriff von System A auf Datenbank B bereitstellt.<\/p>\n<p>Solltest Du einmal eine andere Datenquelle ben&ouml;tigen als die hier vorgestellten, findest Du dort alle denkbaren Konstellationen.<\/p>\n<p>Hier siehst Du auch, dass Verbindungszeichenfolgen nicht immer so umfangreich sein m&uuml;ssen wie die soeben f&uuml;r <b>CurrentProject.Connection <\/b>ermittelte.<\/p>\n<h2>Verbindungszeichenfolge f&uuml;r SQL Server mit Windows-Authentifizierung<\/h2>\n<p>Wenn wir beispielsweise auf eine SQL Server-Datenbank zugreifen wollen, k&ouml;nnen wir grob Verbindungszeichenfolgen f&uuml;r die beiden Authentifizierungsarten Windows-Authentifizierung und SQL ServerAuthentifizierung zusammenstellen.<\/p>\n<p>Die Verbindungszeichenfolge f&uuml;r die Windows-Authentifizierung sieht beispielsweise wie folgt aus &#8211; wobei wir als Servername <b>amvDesktop2023 <\/b>und als Datenbankname <b>Mitarbeiterverwaltung <\/b>verwendet haben:<\/p>\n<pre>Provider=MSOLEDBSQL;Server=amvDesktop2023;Database=Mitarbeiterverwaltung;Trusted_Connection=yes;<\/pre>\n<h2>Verbindungszeichenfolge f&uuml;r SQL Server mit SQL Server-Authentifizierung<\/h2>\n<p>Die Verbindungszeichenfolge f&uuml;r die SQL Server-Authentifizierung sieht so aus. Hier verwenden wir statt dem Parameter <b>Trusted_Connection=yes <\/b>die beiden Parameter <b>UID <\/b>und <b>PWD <\/b>mit den jeweiligen Werten:<\/p>\n<pre>Provider=MSOLEDBSQL;Server=amvDesktop2023;Database=Mitarbeiterverwaltung;UID=[Benutzername];PWD=[Kennwort];<\/pre>\n<h2>Verbindungszeichenfolge ohne Angabe der Datenbank<\/h2>\n<p>Wir k&ouml;nnen die beiden zuvor beschriebenen Verbindungszeichenfolgen auch ohne die Angabe einer Datenbank verwenden. Hier wird dann standardm&auml;&szlig;ig die <b>master<\/b>-Datenbank als Datenbank genutzt. Wir wir herausfinden k&ouml;nnen, welche Datenbank verwendet wird, zeigen wir weiter unten mit der Eigenschaft <b>DefaultDatabase<\/b>.<\/p>\n<h2>Verbindungszeichenfolge f&uuml;r Access-Datenbanken<\/h2>\n<p>Und wenn wir die Verbindungszeichenfolge f&uuml;r den Zugriff auf eine andere Access-Datenbank ben&ouml;tigen, stellen wir diese wie folgt zusammen &#8211; hier f&uuml;r eine Datenbank namens <b>ADODB_Test.accdb<\/b>:<\/p>\n<pre>Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\\...\\ADODB_Test.accdb;Persist Security Info=False;<\/pre>\n<p>Egal, ob wir eine reine Access-Connection erstellen oder eine f&uuml;r den SQL Server: Die angegebenen, teilweise nur aus vier Parametern bestehenden Verbindungszeichenfolgen werden nach dem Zuweisen automatisch um weitere Parameter erg&auml;nzt, die mit Standardwerten gef&uuml;llt werden.<\/p>\n<h2>&Ouml;ffnen und Testen der Datenbankverbindung<\/h2>\n<p>Ob die Datenbankverbindung f&uuml;r die angegebene Verbindungszeichenfolge funktioniert, erfahren wir nur durch das &Ouml;ffnen der Verbindung. Dazu nutzen wir die <b>Open<\/b>-Methode der <b>Connection<\/b>-Klasse.<\/p>\n<p>Wenn wir dies in unser erstes Beispiel einbauen, in dem wir auf das <b>Connection<\/b>-Objekt der aktuellen Access-Datenbank zugreifen, sieht das wie folgt aus:<\/p>\n<pre><span style=\"color:blue;\">Dim <\/span>cnn<span style=\"color:blue;\"> As <\/span>ADODB.Connection\r\n<span style=\"color:blue;\">Set<\/span> cnn = CurrentProject.Connection\r\ncnn.Open<\/pre>\n<p>Wenn wir dies ausf&uuml;hren, erhalten wir allerdings die Fehlermeldung aus Bild 2. Warum ist das Objekt bereits ge&ouml;ffnet? Weil dieses direkt bei Start der Anwendung ge&ouml;ffnet und bereitgestellt wird. Wir k&ouml;nnen also direkt auf das Objekt zugreifen.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_06\/pic_446_002.png\" alt=\"Fehler beim Versuch, eine ge&ouml;ffnete Verbindung erneut zu &ouml;ffnen\" width=\"699,627\" height=\"328,0271\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Fehler beim Versuch, eine ge&ouml;ffnete Verbindung erneut zu &ouml;ffnen<\/span><\/b><\/p>\n<h2>Pr&uuml;fen, ob Verbindung bereits ge&ouml;ffnet ist<\/h2>\n<p>Wie k&ouml;nnen wir dann auf m&ouml;glichst einfache Weise herausfinden, ob eine solche Verbindung bereits ge&ouml;ffnet ist oder nicht?<\/p>\n<p>Dazu k&ouml;nnen wir die Eigenschaft <b>State <\/b>des <b>Connection<\/b>-Objekts nutzen.<\/p>\n<p>Diese liefert einen der Werte der Enumeration <b>ObjectStateEnum<\/b>, die wie folgt lauten:<\/p>\n<ul>\n<li><b>adStateClosed<\/b> (<b>0<\/b>): Die Verbindung ist geschlossen.<\/li>\n<li><b>adStateOpen<\/b> (<b>1<\/b>): Die Verbindung ist erfolgreich ge&ouml;ffnet.<\/li>\n<li><b>adStateConnecting<\/b> (<b>2<\/b>): Die Verbindung wird gerade hergestellt.<\/li>\n<li><b>adStateExecuting <\/b>(<b>4<\/b>): Eine Abfrage wird gerade ausgef&uuml;hrt.<\/li>\n<li><b>adStateFetching<\/b> (<b>8<\/b>): Daten werden abgerufen.<\/li>\n<\/ul>\n<h2>Funktion zur lesbaren Ausgabe der Konstanten f&uuml;r ObjectStateEnum<\/h2>\n<p>Wir haben f&uuml;r die Enumeration <b>ObjectStateEnum <\/b>eine Funktion geschrieben, die uns f&uuml;r den Zahlenwert die jeweilige Konstante zur&uuml;ckgibt (siehe Listing 1).<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>ObjectStateEnum_String(lngObjectStateEnum<span style=\"color:blue;\"> As Long<\/span>)<span style=\"color:blue;\"> As String<\/span>\r\n     Select Case lngObjectStateEnum\r\n         <span style=\"color:blue;\">Case <\/span>0\r\n             ObjectStateEnum_String = \"adStateClosed\"\r\n         <span style=\"color:blue;\">Case <\/span>1\r\n             ObjectStateEnum_String = \"adStateOpen\"\r\n         <span style=\"color:blue;\">Case <\/span>2\r\n             ObjectStateEnum_String = \"adStateConnecting\"\r\n         <span style=\"color:blue;\">Case <\/span>4\r\n             ObjectStateEnum_String = \"adStateExecuting\"\r\n         <span style=\"color:blue;\">Case <\/span>8\r\n             ObjectStateEnum_String = \"adStateFetching\"\r\n         <span style=\"color:blue;\">Case Else<\/span>\r\n             ObjectStateEnum_String = \"Unbekannter Status\"\r\n     <span style=\"color:blue;\">End Select<\/span>\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: Funktion zur lesbaren Ausgabe der Werte der Enumeration ObjectStateEnum<\/span><\/b><\/p>\n<p>Diese erwartet den Zahlenwert der Eigenschaft <b>State <\/b>und liefert den Namen der jeweiligen Konstanten zur&uuml;ck. Damit k&ouml;nnen wir uns den Namen der Konstanten wie folgt ausgeben lassen:<\/p>\n<pre><span style=\"color:blue;\">Dim <\/span>cnn<span style=\"color:blue;\"> As <\/span>ADODB.Connection\r\n<span style=\"color:blue;\">Set<\/span> cnn = CurrentProject.Connection\r\ncnn.Open\r\n<span style=\"color:blue;\">Debug.Print<\/span> ObjectStateEnum_String(cnn.State)<\/pre>\n<h2>Connection immer wieder schlie&szlig;en<\/h2>\n<p>Bei Datenbankzugriffen ist es, wie auch bei allen anderen Objekten, die man im Laufe einer Session &ouml;ffnet, wichtig, diese auch wieder zu schlie&szlig;en und den Speicherplatz freizugeben.<\/p>\n<p>In den meisten F&auml;llen machen sich Nachl&auml;ssigkeiten hier zwar nicht bemerkbar, aber fr&uuml;her oder sp&auml;ter treten dadurch vielleicht Probleme auf. Deshalb schlie&szlig;en wir eine von uns ge&ouml;ffnete Verbindung zun&auml;chst wie folgt:<\/p>\n<pre>cnn.Close<\/pre>\n<p>Anschlie&szlig;end leeren wir die Objektvariable:<\/p>\n<pre><span style=\"color:blue;\">Set<\/span> cnn = Nothing<\/pre>\n<h2>Unterschiede zwischen server- und clientseitigem Cursor in ADODB<\/h2>\n<p>Die <b>CursorLocation<\/b>-Eigenschaft im <b>ADODB.Connection<\/b>-Objekt legt fest, ob der Cursor auf dem Client oder auf dem Server verarbeitet wird.<\/p>\n<p>Standardm&auml;&szlig;ig wird <b>adUseServer <\/b>(<b>1<\/b>) verwendet, wodurch Abfragen direkt auf dem SQL-Server ausgef&uuml;hrt werden. Dies reduziert die Last auf dem Client und ist effizient bei gro&szlig;en Datenmengen. Allerdings kann die Navigation durch Datens&auml;tze eingeschr&auml;nkt sein, und eine stabile Netzwerkverbindung ist erforderlich.Alternativ kann <b>adUseClient <\/b>(<b>2<\/b>) gesetzt werden, wodurch die Abfrageergebnisse auf den Client-PC geladen werden. Dies erm&ouml;glicht eine vollst&auml;ndige Navigation durch die Daten (<b>MoveFirst<\/b>, <b>MoveLast<\/b>, <b>MovePrevious<\/b>), ist jedoch speicherintensiver.<\/p>\n<p>Ein clientseitiger Cursor eignet sich besonders f&uuml;r Anwendungen mit vielen gleichzeitigen Benutzern oder wenn Daten offline bearbeitet werden sollen.<\/p>\n<p>Diese Einstellung gilt generell f&uuml;r alle Zugriffe, die &uuml;ber diese Connection durchgef&uuml;hrt werden. Es gibt  <b>Recordset<\/b>&#8211; und <b>Command<\/b>-Objekte f&uuml;r den Zugriff. Bei Recordsets k&ouml;nnen wir diese Eigenschaft allerdings noch individuell anpassen, <b>Command<\/b>-Objekte &uuml;bernehmen diese Eigenschaft von der angegebenen Connection.<\/p>\n<h2>Aktuelle Datenbank der Connection einstellen und ermitteln<\/h2>\n<p>Wir k&ouml;nnen in der Verbindungszeichenfolge auf die Angabe einer Datenbank verzichten. Dann wird zum Beispiel bei Zugriff auf den SQL Server die <b>master<\/b>-Datenbank verwendet.<\/p>\n<p>Dass dies der Fall ist, k&ouml;nnen wir mit der Eigenschaft <b>DefaultDatabase<\/b> herausfinden. Diese nutzen wir nach dem Verbinden wie folgt:<\/p>\n<pre><span style=\"color:blue;\">Set<\/span> cnn = <span style=\"color:blue;\">New<\/span> ADODB.Connection\r\nstrConnection = \"Provider=MSOLEDBSQL;Server=amvDesktop2023;Trusted_Connection=yes;\"\r\ncnn.ConnectionString = strConnection\r\ncnn.Open\r\n<span style=\"color:blue;\">Debug.Print<\/span> cnn.DefaultDatabase\r\n...<\/pre>\n<h2>Datenbank f&uuml;r eine Verbindung wechseln<\/h2>\n<p>Mit der <b>DefaultDatabase<\/b>-Eigenschaft k&ouml;nnen wir aber auch zur Laufzeit bei ge&ouml;ffneter Verbindung die Datenbank wechseln. Dazu weisen wir dieser einfach den Namen der gew&uuml;nschten Datenbank zu:<\/p>\n<pre>cnn.DefaultDatabase = \"Mitarbeiterverwaltung\"<\/pre>\n<h2>Provider der Verbindung ermitteln<\/h2>\n<p>Den Provider geben wir normalerweise direkt mit der Verbindungszeichenfolge an.<\/p>\n<p>Wir k&ouml;nnen diesen aber auch mit der Eigenschaft <b>Provider <\/b>des <b>Connection<\/b>-Objekts angeben.<\/p>\n<p>F&uuml;r den SQL Server verwenden wir f&uuml;r aktuelle Versionen (ab SQL Server 2012) diesen Provider:<\/p>\n<pre>MSOLEDBSQL<\/pre>\n<p>F&uuml;r &auml;ltere SQL Server-Versionen k&ouml;nnen wir diesen Provider nutzen:<\/p>\n<pre>SQLOLEDB<\/pre>\n<p>F&uuml;r Access-Datenbanken:<\/p>\n<pre>ACE.OLEDB.12.0<\/pre>\n<h2>Fehler beim Zugriff mit ADODB auswerten<\/h2>\n<p>Wenn beim Zugriff auf eine SQL Server-Datenbank Fehler auftreten, k&ouml;nnen wir diese mit der herk&ouml;mmlichen <b>Err<\/b>-Klasse nur bedingt analysieren.<\/p>\n<p>Deshalb bietet uns ADODB f&uuml;r das <b>Connection<\/b>-Objekt eine eigene <b>Errors<\/b>-Auflistung.<\/p>\n<p>Wie man diese nutzt und welche Besonderheiten es insgesamt bei der Fehlerbehandlung bei den Zugriffstechniken DAO und ADODB gibt, beschreiben wir im Artikel <b>SQL Server: Fehlerbehandlung in DAO und ADODB<\/b> (<b>www.vbentwickler.de\/****<\/b>).<\/p>\n<h2>Verschiedene Modi f&uuml;r den Datenbankzugriff<\/h2>\n<p>Mit der <b>Mode<\/b>-Eigenschaft des <b>Connection<\/b>-Objekts k&ouml;nnen wir die Art des Datenzugriffs festlegen.<\/p>\n<p>Die Eigenschaft kann die folgenden Werte annehmen:<\/p>\n<ul>\n<li><b>adModeUnknown <\/b>(<b>0<\/b>): Standardwert, der den Modus nicht explizit festlegt.<\/li>\n<li><b>adModeRead <\/b>(<b>1<\/b>): Schreibgesch&uuml;tzter Zugriff auf die Datenquelle.<\/li>\n<li><b>adModeWrite <\/b>(<b>2<\/b>): Nur Schreibzugriff auf die Datenquelle (kein Lesezugriff).<\/li>\n<li><b>adModeReadWrite <\/b>(<b>3<\/b>): Lese- und Schreibzugriff auf die Datenquelle.<\/li>\n<li><b>adModeShareDenyNone <\/b>(<b>4<\/b>): Keine Einschr&auml;nkungen f&uuml;r andere Verbindungen.<\/li>\n<li><b>adModeShareDenyRead <\/b>(<b>8<\/b>): Andere Verbindungen k&ouml;nnen nicht lesend zugreifen.<\/li>\n<li><b>adModeShareDenyWrite <\/b>(<b>16<\/b>): Andere Verbindungen k&ouml;nnen nicht schreibend zugreifen.<\/li>\n<li><b>adModeShareExclusive <\/b>(<b>32<\/b>): Exklusiver Zugriff &#8211; keine anderen Verbindungen erlaubt.<\/li>\n<li><b>adModeShareDenyReadWrite <\/b>(<b>64<\/b>): Andere Verbindungen k&ouml;nnen weder lesend noch schreibend zugreifen.<\/li>\n<li><b>adModeRecursive <\/b>(<b>256<\/b>): Wird f&uuml;r hierarchische Recordsets verwendet.<\/li>\n<\/ul>\n<h2>ADODB-Version ermitteln<\/h2>\n<p>Mit der Eigenschaft <b>Version <\/b>k&ouml;nnen wir die Version der ADODB-Bibliothek ermitteln.<\/p>\n<p>Dazu brauchen wir keine Connection zu &ouml;ffnen, das Erstellen allein reicht aus, um auf diese Eigenschaft zuzugreifen:<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>ADODBVersion()\r\n     <span style=\"color:blue;\">Dim <\/span>cnn<span style=\"color:blue;\"> As <\/span>ADODB.Connection\r\n     <span style=\"color:blue;\">Set<\/span> cnn = <span style=\"color:blue;\">New<\/span> ADODB.Connection\r\n     <span style=\"color:blue;\">Debug.Print<\/span> cnn.Version\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p>F&uuml;r die in diesem Beispiel verwendete Bibliothek <b>Microsoft ActiveX Data Objects 6.1 Library <\/b>erhalten wir den Wert <b>10<\/b>.<\/p>\n<h2>Die Property-Auflistung der Connection-Klasse<\/h2>\n<p>Wie viele andere Klassen liefert auch die <b>Connection<\/b>-Klasse eine <b>Properties<\/b>-Auflistung.<\/p>\n<p>Diese durchlaufen wir wie folgt:<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>ADODBProperties()\r\n     <span style=\"color:blue;\">Dim <\/span>cnn<span style=\"color:blue;\"> As <\/span>ADODB.Connection\r\n     <span style=\"color:blue;\">Dim <\/span>prp<span style=\"color:blue;\"> As <\/span>ADODB.Property\r\n     <span style=\"color:blue;\">Set<\/span> cnn = <span style=\"color:blue;\">New<\/span> ADODB.Connection\r\n     For Each prp In cnn.Properties\r\n         <span style=\"color:blue;\">Debug.Print<\/span> prp.Name, prp.Value\r\n     <span style=\"color:blue;\">Next<\/span> prp\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p>Wenn wir diese wie oben f&uuml;r ein frisch erstelltes <b>Connection<\/b>-Objekt ausf&uuml;hren, erhalten wir nur wenige Eigenschaften mit den entsprechenden Werten (siehe Bild 3).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_06\/pic_446_003.png\" alt=\"Ausgabe der Properties des Connection-Objekts\" width=\"424,6267\" height=\"264,5961\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 3: Ausgabe der Properties des Connection-Objekts<\/span><\/b><\/p>\n<p>Wenn wir allerdings eine Verbindungszeichenfolge definieren und wie folgt erst danach die Properties durchlaufen, erhalten wir ein anderes Ergebnis:<\/p>\n<pre><span style=\"color:blue;\">Dim <\/span>strConnection<span style=\"color:blue;\"> As String<\/span>\r\n<span style=\"color:blue;\">Dim <\/span>cnn<span style=\"color:blue;\"> As <\/span>ADODB.Connection\r\n<span style=\"color:blue;\">Dim <\/span>prp<span style=\"color:blue;\"> As <\/span>ADODB.Property\r\n<span style=\"color:blue;\">Set<\/span> cnn = <span style=\"color:blue;\">New<\/span> ADODB.Connection\r\nstrConnection = \"Provider=MSOLEDBSQL;Server=amvDesktop2023;Trusted_Connection=yes;\"\r\ncnn.ConnectionString = strConnection\r\nFor Each prp In cnn.Properties\r\n     <span style=\"color:blue;\">Debug.Print<\/span> prp.Name, prp.Value\r\n<span style=\"color:blue;\">Next<\/span> prp<\/pre>\n<p>Danach sieht die Ausgabe der Eigenschaften wie in Bild 4 aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_06\/pic_446_004.png\" alt=\"Ausgabe der Properties des Connection-Objekts mit Verbindungszeichenfolge\" width=\"549,6265\" height=\"665,808\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 4: Ausgabe der Properties des Connection-Objekts mit Verbindungszeichenfolge<\/span><\/b><\/p>\n<h2>&Ouml;ffnen von Connections<\/h2>\n<p>Bisher haben wir die <b>Open<\/b>-Methode immer ohne Parameter verwendet. Allerdings bietet diese Methode durchaus verschiedene Parameter an:<\/p>\n<ul>\n<li><b>ConnectionString<\/b>: Verbindungszeichenfolge. Diese haben wir in den bisherigen Beispielen immer &uuml;ber die gleichnamige Eigenschaft des <b>Connection<\/b>-Objekts angegeben. Wir k&ouml;nnen sie jedoch auch als Parameter angeben.<\/li>\n<li><b>UserID<\/b>: Benutzername. Diesen k&ouml;nnen wir auch in der Verbindungszeichenfolge unterbringen. Er ist nur bei Verbindungen mit SQL Server-Authentifizierung erforderlich.<\/li>\n<li><b>Password<\/b>: Auch das Kennwort kann Teil der Verbindungszeichenfolge sein. Auch dieses ist nur bei Verbindungen mit SQL Server-Authentifizierung erforderlich.<\/li>\n<li><b>Options <\/b>(Standardwert <b>-1<\/b>): Nimmt Werte der Enumeration <b>ConnectOptionEnum <\/b>entgegen. Es gibt nur zwei M&ouml;glichkeiten: <b>adConnectUnspecified <\/b>(<b>-1<\/b>) ist der Standardwert hier ist keine spezifische Option gesetzt. <b>adAsyncConnect <\/b>(<b>1<\/b>) &ouml;ffnet die Verbindung asynchron. Die Methode gibt sofort die Kontrolle zur&uuml;ck, w&auml;hrend die Verbindung im Hintergrund hergestellt wird.<\/li>\n<\/ul>\n<p>Die Verwendung von <b>adAsyncConnect <\/b>sorgt daf&uuml;r, dass die aufrufende Prozedur tats&auml;chlich direkt die n&auml;chste Anweisung ausf&uuml;hrt.<\/p>\n<p>Wenn diese beispielsweise ein Recordset auf Basis der zuvor zu &ouml;ffnenden Connection &ouml;ffnen soll, kann das zu einem Fehler f&uuml;hren, weil die Verbindung noch nicht hergestellt wurde.<\/p>\n<p>Ein sinnvoller Einsatzzweck w&auml;re, wenn man wei&szlig;, dass das Herstellen der Verbindung l&auml;nger dauern kann, diese bereits beim Starten der Anwendung zu &ouml;ffnen und diese dann sp&auml;ter zum Zugriff auf die Daten zu nutzen.<\/p>\n<h2>Schlie&szlig;en von Connections<\/h2>\n<p>Die <b>Close<\/b>-Methode der <b>Connection<\/b>-Klasse trennt die Verbindung zur Datenquelle. Sie gibt Systemressourcen frei, die von der Verbindung genutzt wurden und setzt die <b>State<\/b>-Eigenschaft der Verbindung auf <b>adStateClosed<\/b> (<b>0<\/b>). Falls offene Recordset- oder Command-Objekte existieren, bleiben diese erhalten, sind aber m&ouml;glicherweise nicht mehr verwendbar.<\/p>\n<p>Wir sollten die <b>Close<\/b>-Methode immer aufrufen, wenn die Connection nicht mehr ben&ouml;tigt wird. Ein erneutes Aufrufen bei einer bereits geschlossenen Verbindung l&ouml;st einen Fehler aus.<\/p>\n<h2>Abbrechen des Verbindungsaufbaus<\/h2>\n<p>Mit der <b>Cancel<\/b>-Methode k&ouml;nnen wir beispielsweise den Aufbau einer Verbindung abbrechen, wenn dieser zu lange dauert.<\/p>\n<p>Das k&ouml;nnen wir in Zusammenhang mit dem Parameter <b>adAsyncConnect <\/b>nutzen. Im folgenden Beispiel stellen wir den <b>ConnectionTimeout <\/b>auf f&uuml;nf Sekunden ein, &ouml;ffnen die Verbindung mit <b>adAsyncConnect <\/b>und lassen dann eine <b>Do While<\/b>-Schleife laufen, solange die Verbindung noch nicht hergestellt ist.<\/p>\n<p>War dieser nach f&uuml;nf Sekunden noch nicht erfolgreich, wird die <b>Cancel<\/b>-Methode aufgerufen. Deren Ausf&uuml;hrung kann noch einige Sekunden dauern, bis der asynchrone Verbindungsaufbau beendet ist.<\/p>\n<p>Zumindest wissen wir aber hier bereits nach der angegebenen Zeit, dass die Verbindung wohl nicht ge&ouml;ffnet werden kann:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>AsynchronerAufbauMitAbbruch()\r\n     <span style=\"color:blue;\">Dim <\/span>cnn<span style=\"color:blue;\"> As <\/span>ADODB.Connection\r\n     <span style=\"color:blue;\">Dim <\/span>dblStart<span style=\"color:blue;\"> As Double<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> cnn = CreateObject(\"ADODB.Connection\")\r\n     cnn.Open \"Provider=SQLOLEDB;...\", , , adAsyncConnect    \r\n     dblStart = Timer\r\n     <span style=\"color:blue;\">Do While<\/span> cnn.State = adStateConnecting\r\n         DoEvents\r\n         <span style=\"color:blue;\">Debug.Print<\/span> Timer, dblStart, Timer - dblStart\r\n         <span style=\"color:blue;\">If <\/span>Timer - dblStart &gt; 5<span style=\"color:blue;\"> Then<\/span>\r\n             <span style=\"color:blue;\">Debug.Print<\/span> _\r\n                 \"Verbindungsaufbau wird abgebrochen.\"\r\n             cnn.Cancel\r\n             <span style=\"color:blue;\">Debug.Print<\/span> \"Verbindungsaufbau abgebrochen!\"\r\n             <span style=\"color:blue;\">Exit Sub<\/span>\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Loop<\/span>\r\n     <span style=\"color:blue;\">Debug.Print<\/span> \"Verbindungsaufbau erfolgreich.\"\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<h2>Die Execute-Methode<\/h2>\n<p>Die Execute-Methode liefert schnelle M&ouml;glichkeiten, &uuml;ber die Connection direkt Recordsets zu f&uuml;llen oder Aktionsabfragen auszuf&uuml;hren.<\/p>\n<p>Wir gehen in einem eigenen Artikel namens ADODB: SQL-Befehle schnell ausf&uuml;hren mit Execute (<b>www.vbentwickler.de\/447<\/b>) auf diese Methode ein.<\/p>\n<h2>Die OpenSchema-Methode<\/h2>\n<p>Diese Methode erlaubt uns, Metadaten &uuml;ber die Elemente einer Datenbank abzurufen. Auch diesem Thema widmen wir einen eigenen Artikel: <b>ADODB: Datenbankinformationen mit OpenSchema ermitteln <\/b>(<b>www.vbentwickler.de\/469<\/b>).<\/p>\n<h2>Transaktionen mit ADODB<\/h2>\n<p>Die <b>Connection<\/b>-Klasse bietet sowohl die Methoden zum Starten, Abschlie&szlig;en oder Zur&uuml;cksetzen von Transaktionen (wie <b>BiginTrans<\/b>, <b>CommitTrans <\/b>und <b>RollbackTrans<\/b>) als auch noch eine weitere Eigenschaft, mit der wir das Verhalten beim Durchf&uuml;hren von Transaktionen beeinflussen k&ouml;nnen (<b>IsolationLevel<\/b>).<\/p>\n<p>Diese schauen wir uns in einem weiteren Artikel namens <b>Transaktionen mit ADODB und SQL Server <\/b>(<b>www.vbentwickler.de\/450<\/b>) an.<\/p>\n<h2>Downloads zu diesem Beitrag<\/h2>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>ADODB_Connections.accdb<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/A2E98B69-B779-4D46-A6AB-993AB3FC835E\/vbe_446.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Wer auf die Inhalte von Datenbanken wie Access, SQL Server und anderen zugreifen m&ouml;chte, ben&ouml;tigt eine spezielle Datenzugriffstechnologie. Unter VB6, VBA und twinBASIC verwendet man dazu in der Regel die DAO-Bibliothek, in Office &#8220;Microsoft Office 16.0 Access database engine Object Library&#8221; genannt, oder die ADODB-Bibliothek (&#8220;Microsoft ActiveX Data Objects 6.1 Library&#8221;). Geschichtlich wurde mal die eine, mal die andere von Microsoft als die zu bevorzugende Datenzugriffstechnik bezeichnet. Derzeit verwendet man meist DAO, vor allem in Verbindung mit Access-Datenbanken, aber beim Zugriff auf SQL Server-Datenbanken bietet ADODB einige Features, die wir mit DAO nicht nutzen k&ouml;nnen. In diesem Artikel steigen wir in die Programmierung von Datenbankzugriffen mit ADODB ein. Dabei schauen wir uns als Erstes die Connection-Klasse an, mit der erst einmal eine Verbindung zur Datenbank aufgebaut werden kann.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[662024,66062024,44000008],"tags":[],"yst_prominent_words":[],"class_list":["post-55000446","post","type-post","status-publish","format-standard","hentry","category-662024","category-66062024","category-Datenzugriffstechnik"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000446","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/comments?post=55000446"}],"version-history":[{"count":0,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000446\/revisions"}],"wp:attachment":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/media?parent=55000446"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/categories?post=55000446"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/tags?post=55000446"},{"taxonomy":"yst_prominent_words","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/yst_prominent_words?post=55000446"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}