PDA

Vollständige Version anzeigen : ADODB.Recordset an Form binden


mpaus
21.04.2011, 21:09
Hallo zusammen!

Ich versuche unter Access 2007 (accdb) mit folgenden Funktionen ein ADODB.Recordset an ein Formular zu binden:

Private Function conConnection() As ADODB.Connection
Dim con As ADODB.Connection

Set con = New ADODB.Connection

With con
.Provider = "SQLOLEDB.1"
.CursorLocation = adUseClient
.Properties("Data Source") = m_sServer
.Properties("Application Name") = C_ConnectionName
.Properties("Initial Catalog") = m_sDB

If m_bWinAuth = True Then
.Properties("Integrated Security") = "SSPI"
Else
.Properties("User ID") = m_sBenutzer
.Properties("Password") = m_sPasswort
End If

.Properties("Persist Security Info") = False
.CursorLocation = adUseClient

End With

Set conConnection = con

End Function

Public Function rsOpenRecordset(ByVal sSQL As String, ByVal nCursorType As ADODB.CursorTypeEnum, Optional ByVal nLockType As ADODB.LockTypeEnum = adLockReadOnly) As ADODB.Recordset
Dim con As ADODB.Connection
Dim rs As New ADODB.Recordset


Set con = conConnection
con.Open
rs.Open sSQL, con, nCursorType, nLockType
Set rsOpenRecordset = rs

End Function


Im Formular sieht das dann wie folgt aus:

Private Sub Form_Load()
Dim sSQL As String

sSQL = "SELECT * FROM Adressen"
Set Me.Recordset = goMandant.oData.rsOpenRecordset(sSQL, adOpenDynamic, adLockOptimistic)

End Sub


Die Datenbank ist ein SQL Server 2008. Betriebsystem ist Win7 ohne SP1.
Leider stürzt Access in der Zeile Set Me.Recordset... komplett ab (Access funktioniert nicht mehr). Der Absturz erfolgt ganz exakt nach dem Verlassen der Funktion rsOpenRecordset.

Ich hoffe ja sehr, dass ich irgenwas falsch mache. Ich hoffe, einer von euch hat einen Rat für mich.

Schöne Ostertage schon mal!

ebs17
21.04.2011, 21:21
Wie wäre es, wenn Du das Set weglässt (das Recordset ist hier eine Eigenschaft und keine Objektvariable).

mpaus
21.04.2011, 21:37
Dann kommt Laufzeitfehler 91, Objetvariable oder With-Blockvariable nicht festgelegt.

Josef P.
22.04.2011, 07:11
Hallo!

Set passt schon, da eine Referenz übergeben wird.

Grundsätzlich sieht der Code richtig aus. Da im gezeigten Code aber nicht sichtbar ist, was beim Verlassen von goMandant und oData passiert, könnte der Fehler auch dort stecken.
Eventuell probierst du auch noch adOpenKeyset statt adOpenDynamic aus. Das sollte aber eigentlich egal sein. Wichtig ist nur der clientseitige Cursor, den du aber bereits in der Connection einstellst.
BTW: Warum öffnest du eigentlich immer eine neue Connection? Ist die Serververbindung so instabil, dass du eine Connection nicht offen halten kannst?

mfg
Josef

mpaus
22.04.2011, 12:03
Mit dem goMandant usw. hats nichts zu tun. Es funtkioniert auch nicht ohne.
Ich habe mal ein Beispiel angehängt. Aus meiner Sicht ist der Code auch richtig...

@Josef:Das mit der Connection ist anscheinend eine Frage der Philosophie. In einem VB Forum hat man mir geschrieben, dass man doch eine Verbindung nicht einfach offen lassen könne. Die müsse immer geschlossen werden.
Ich habe ehrlich gesagt keine Ahnung was nun besser ist...

mpaus
24.04.2011, 10:36
Ich habe auch adOpenKeyset statt adOpenDynamic verwendet. Access geht immer wieder zu...

Josef P.
25.04.2011, 18:51
Hallo!

Bei mir funktioniert deine Beispiel-mdb. (Wobei ich natürlich andere Verbindungsdaten und einen anderen Tabellennamen verwendete.)

Bezüglich "offener Verbindung": die ist sowieso offen solange du das REcordset offen hast und dessen Connection nicht kappst. => Somit kann man meiner Ansicht nach auch die Connection-Referenz in einer extra Variablen halten.

mfg
Josef

mpaus
26.04.2011, 07:46
Hallo Josef!

Es ist ja eine accdb. Hast du das Fomrular nach Access 2003 importiert?
Ich habe so langsam das Gefühl, dass es sich um ein Problem von Access 2007 handelt.

Josef P.
26.04.2011, 07:50
Hallo!

... dann funktioniert eben deine Beispiel-accdb bei mir. ;) Ich testete allerdings mit Access 2010 und nicht mit 2007.

Würde eine ADODB-Recordset-Zuweisung mit dem ACE-Provider funktionieren?
... also ein ADODB-Recordset aus einem accdb-Backend.

mfg
Josef

avogt_at_home
26.04.2011, 07:52
Hallo,
wo wir schon bei diesem Problem sind, ich hät da gerne auch noch eines.
Wie kann ich ein ADODB RS und ein Listenfeld zusammenbringen? Geht das direkt oder muss ich in der RS-Schleife die Werteliste erstellen?

Gruß und sorry fürs OT
Andreas

Josef P.
26.04.2011, 08:00
Hallo!

@Andreas: ab Access 2002 kannst du auch ein ADODB-Recordset an ein Listenfeld binden (Auch das Listenfeld/Listbox hat eine Recordset-Eigenschaft). Dabei aber beachten, dass ein clientseitiger Cursor verwendet werden muss.

mfg
Josef

mpaus
26.04.2011, 08:20
Ich dreh durch:

Ich habe die Function jetzt für den Zugriff auf eine accdb abgeändert. Damit klappt es.
Ich hatte den Connection String zur Vereinfachung einfach in der .ConnectionString Eigenschaft angegeben.
Nach dem das nun funktionierte, habe ich den Connection String für den SQL Server auch so eingegeben und siehe da, es klappt auch!


Private Function conConnection() As ADODB.Connection
Dim con As ADODB.Connection

Set con = New ADODB.Connection

With con
.CursorLocation = adUseClient
' .ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & CurrentProject.Path & "\Beispiel.accdb;Persist Security Info=False;"
.ConnectionString = "Provider=SQLNCLI10;Server=NB;Database=MyDatabase;Uid=sa;Pwd=Test;"
End With

Set conConnection = con

End Function


Damit funktioniert die Bindung nun also einwandfrei.
Wenn ich jetzt noch rausbekomme, was an der vorherigen Function falsch war, wäre ich ja glücklich. Lag es am anderen Provider, den ich genommen habe?

mpaus
26.04.2011, 09:38
Jetzt verstehe ich die Welt gar nicht mehr:

Die Bindung klappt nur, wenn ich an das Formular vorher ein Recordset binde, dessen Daten aus einer accdb kommen.

Also, ich muss erst an irgendein Formular ein Recordset binden, das auf eine accdb zugreift. Danach erst kann ich die Bindung an den SQL-Server vornehmen. Und dann ist es auch egal, welches Formular ich nehme.
Wenn ich diesen Schritt unterlasse, geht Access wieder zu...

Ich habe die Datei nochmal zum Verständnis angehängt.

Josef P.
26.04.2011, 11:10
Hallo!

Tritt das Problem bei dir auch in der Beispiel-Anwendung (Datenbank1.accdb) ohne <code>Set Me.Recordset = rsOpenRecordset(sSQL, adOpenKeyset, , True)</code> auf?
Versuche einmal ADODB 2.1 und probiere auch aus, ob es hilft, wenn du <code>rs.CursorLocation = adUseClient</code> vor dem Öffnen des Recordset setzt.

mfg
Josef

mpaus
26.04.2011, 11:57
Hallo!

Ja, in meiner Beispielanwendung stürzt Access auch ab, wenn ich den Code so abändere:

Private Sub Form_Load()
Dim sSQL As String

sSQL = "SELECT * FROM KHKAdressen"
'Set Me.Recordset = rsOpenRecordset(sSQL, adOpenKeyset, , True)
Set Me.Recordset = rsOpenRecordset(sSQL, adOpenKeyset)

End Sub


Ich habe den Verweis auf ADO 2.7 gesetzt -> Access stürzt ab.
Ich habe den Verweis auf ADO 2.1 gesetzt -> Access stürzt ab.

Ich habe dann den Code wie folgt geändert:

Private Function rsOpenRecordset(ByVal sSQL As String, ByVal nCursorType As ADODB.CursorTypeEnum, Optional ByVal nLockType As ADODB.LockTypeEnum = adLockReadOnly, Optional bAccess As Boolean = False) As ADODB.Recordset
Dim con As ADODB.Connection
Dim rs As New ADODB.Recordset

Set con = conConnection(bAccess)
con.Open

rs.CursorLocation = adUseClient
rs.Open sSQL, con, nCursorType, nLockType
Set rsOpenRecordset = rs

End Function

-> Access stürzt ab.

avogt_at_home
28.04.2011, 19:50
Hallo,
als Nachtrag zu ADODB Recordset an Listenfeld/Kombinationsfeld binden habe ich folgenden Artikel gefunden:
http://support.microsoft.com/kb/282358/en-us?fr=1

Demnach empfiehlt Microsoft keine Recordset-Bindung sondern per VBA die Befüllung einer Werteliste.
Hat bei mir auch gut geklappt.

Gruß Andreas

mpaus
02.05.2011, 11:56
Hallo,

dass man bei den Controlls die Werteliste nutzen soll, war mir bekannt.
Aber bei Formularen finde ich gebundene Formulare einfach klasse, da einem die Bindung erheblich Arbeit erspart.