Hi,
ich stelle meine Datenbank schritt für Schritt von Tabellen auf Recordsets um, welche von einer SQL Datenbank geholt werden. Bei einem Formular habe ich es wie folgt im Klassenmodul umgesetzt:
Option Compare Database
Option Explicit
Dim rs As New ADODB.Recordset
Dim con As New ADODB.Connection
Dim sql As String
Private Sub Form_Load()
holeRecordset
End Sub
Sub holeRecordset()
Dim sql As String
sql = "EXEC dbo.spkundensuche 1, 2"
VerbindungStellen
Set rs = New ADODB.Recordset
With rs
.Source = sql
.ActiveConnection = con
.CursorType = adOpenKeyset
.LockType = adLockReadOnly
.Open
End With
Set Me.Recordset = rs
rs.Close
End Sub
Sub VerbindungStellen()
With con
.Provider = "MSDataShape"
.ConnectionString = "DATA PROVIDER=SQLOLEDB.1;Server=*************************;"
.CursorLocation = adUseServer
.Open
End With
End Sub
Nun möchte ich aber die Subs in eine Funktion in einem normalen Modul auslagern. Hierbei sollte es so sein, dass ich in jedem Formular im Ereignis "beim Laden" mit einer einfachen Codezeile den Recordset holen kann. Dies sollte dann ungefähr wie folgt aussehen:
Private Sub Form_Load()
Set Me.Recordset = Recordsetholen, "sql-Befehl"
End Sub
Leider kenne ich mich noch nicht so gut damit aus, wie ich die Variablen - Gültigkeit hierfür legen muss und wie die Variablen dann innerhalb der neuen Funktionen zu verbinden sind (ByVal // ByRef)....
Weiterhin sollte der Recordset bis zum schließen des Fensters geöffnet sein, damit Änderungen am Datensatz auch übernommen werden können. Beim schließen des Fensters müsste der Recordset und die Verbindung dann sicher irgendwie geschlossen werden.
Ich freue mich auf Eure Hilfen dazu.
LG
datekk
Hi,
ich hatte hier vor einiger Zeit doch funktionierende Beispiele gepostet...
Es gibt folgende Möglichkeiten, die Referenz auf ein Recordset in ein Formular zu bekommen.
Entweder über eine öffentliche Funktion, die als Rückgabewert ein Recordset hat.
Public Function getDaten() as ADODB.Recordset
Sie wird vom Formular so aufgerufen
Dim rs as ADODB.Recordset (Im Formular)
Set rs = getDaten() (Im Öffnen-Ereignis)
Oder über einen Referenzparameter in einem Sub
Public Sub getDaten(ByRef rs ADODB.Recordset)
Dim rs as ADODB.Recordset (im Formular)
Call getDaten(rs)
Ein Übergabeparameter byval würde keinen Sinn machen und er wird auch stillschweigend beim kompilieren so behandelt, als ob man byref geschrieben hätte.
Nachdem Du die Referenz auf das Recordset hast, kannst Du mit diesem auch alles machen, zu Beispiel dieses schließen bei Schließen des Formulars.
Hi Wurliwurm,
Deine Beispiele sind bei mir auch Grundlage der technischen Realisierung innerhalb der Formulare, und dort funktioniert es auch super. Nun möchte ich die Subs sozusagen in Funktionen in einem Modul "zentralisieren" damit ich nicht jedes Klassenmodul so aufblähen muss. Mein Ziel ist es, meine Datenbank völlig ohne eingebundene Tabellen zu betreiben und die Arbeit vollständig dem SQL Server aufzubürden... einfach der Geschwindigkeit und Datensicherheit wegen. Daher muss ich nun alle der gefühlten 1000 Formular so umstellen und suche daher nach einem optimierten Recordset.
Ich danke Dir für Deine Ansätze und melde mich kurzfristig wieder.
LG
Zitat von: datekk am Oktober 12, 2016, 14:33:02
Daher muss ich nun alle der gefühlten 1000 Formular so umstellen und suche daher nach einem optimierten Recordset.
Der Ansatz ist sehr gut und wird auch funktionieren.
Du könntest eine zentrale und generische Funktion schreiben, welche Recordsets zurückgibt für einen SQL-String. In der Art:
Public Function holeRecordset(ByVal strSQL as String) as ADODB.Recordset
Wie bei Endlosformularen die Anzeige im Formular mit CursorLocation aduseServer sein wird, weiß ich nicht sicher. Ich umschiffe das ja mit dem Kopieren in lokale ungebundene Recordsets mit aduseClient, was ein kleiner Overhead ist, aber kaum spürbare Performancenachteile hat.
In meinen Anwendungen ist die ADODB.Connection immer eine public Variable. Die Connection wird gleich beim Starten des Access-Clients geöffnet und bleibt immer offen. Es ist völlig unnötig, sie zwischendrin neu aufzubauen. Bei Abstürzen oder Netzwerkfehlern mit Trennung des Clients wird der Server erkennen, daß die Connection weggebrochen ist, das ist sauber im Gegensatz zu filebasierten Backends.
Viel gibt es m.E. nicht zu tun, es gehört alles zum Verbindungsaufbau (conn.open) und Recordset-Öffnen (conn.open) in die Module. In den Formularen higegen wird nur ein Recordset referenziert mit
Dim rs as ADODB.Recordset
und die Felder müssen angebunden werden.
''***Felder anbinden an das Recordset***
Set Me.Recordset = rs
txt1.ControlSource = "Betrag"
txt2.ControlSource = "Kontonummer"
Hallo!
Man kann bei Bedarf auch das Recordset mit adUseClient öffnen. (Ist meiner Meinung nach aber nur für das Ändern der Daten über das gebundene Formular bzw. für das Kappen der Verbindung erforderlich.)
Eine Standardroutine von mir (Auszug aus der AdodbHandler-Klasse (http://source.access-codelib.net/filedetails.php?repname=CodeLib+%28Entwurf%2C+branches%2Fdraft%29&path=%2Fdata%2Fado%2FAdodbHandler.cls)):
Public Function OpenRecordset(ByVal Source As String, _
Optional ByVal CursorType As ADODB.CursorTypeEnum = ADODB.CursorTypeEnum.adOpenForwardOnly, _
Optional ByVal LockType As ADODB.LockTypeEnum = ADODB.LockTypeEnum.adLockReadOnly, _
Optional ByVal CursorLocation As ADODB.CursorLocationEnum = ADODB.CursorLocationEnum.adUseServer, _
Optional ByVal DisconnectedRecordset As Boolean = False) As ADODB.Recordset
' gibt geöffnetes ADO-Recordset zurück
' Source = SQL-Anweisung
Dim rst As ADODB.Recordset
Set rst = New ADODB.Recordset
With rst
.CursorLocation = CursorLocation
.Open Source, Me.CurrentConnection, CursorType, LockType
If DisconnectedRecordset Then
Set .ActiveConnection = Nothing
End If
End With
Set OpenRecordset = rst
End Function
Der Aufruf erfolgt dann z. B. mit
Set FormRef.Recordset = StatischeAdodbHandlerInstanz.OpenRecordset("[SQL-Anweisung]", adOpenKeyset, adLockReadOnly, adUseClient)
.. das sollte bei Endlosformularen ohne Probleme laufen.
Anm.: Den CursorType passt sich Access (glaube ich zu erinnern) selbst an, sobald man das Recordset an das Formular bindet.
Bezüglich gebundener Datenfelder gehe ich pragmatisch vor:
Ich stelle als Datenquelle einen SQL-Ausdruck mit einer Dummy-Tabelle um alle benötigten Datenfelder im Formularentwurf verwenden zu können und binde damit die Steuerelemente. Dann muss man später mittels Code nichts anpassen. ;)
Prinzip: select 0 as Feld1, "" as Feld2, .. from EineBeliebigeClientTabelle where 1=0
mfg
Josef