none
Access 2010 Laufzeitfehler 3048 - "Mehr Datenbanken können nicht geöffnet werden."

    Frage

    1. 3-4 Frontend DB greifen permanent auf 11 Backend DB zu (auch mit VBA): Bekomme immer wieder folgende Fehlermeldungen: Laufzeitfehler 3048 - "Mehr Datenbanken können nicht geöffnet werden." und zu wenig Systemresourcen. Gefundene Lösung ConstMaxRsCount AsLong=10000 Dim rs() As Recordset ReDim rs(MaxRsCount) Gilt dies nur für den einen rs ? – Muß ich bei jeder Deklaration eines neuen rs wiederholen ?
    2.   Beim Schließen eines Formulars mit vielen Unterformularen werden die rs´s geschlossen?
    Freitag, 16. November 2012 13:07

Alle Antworten

  • 1. ein Hallo oder ähnlichtes zu Beginn der Frage wäre schön, das hier ist keine kostenpflichtige Hotline.
    2. Name wäre schön, dann könnte man Dich anreden.

    Hallo,
    Wenn Du deinen Quelltext schickst, das Stück mit dem Teil um den es geht, wäre es leichter etwas sinnvolles zu schreiben.
    Meine Kristallkugel ist bereits im Wochenende.
    Wozu möchtest Du ein Recordset mit 1000 Elementen Dimensionieren, wenn es doch 11 Backends gibt?

    Warum möchtest Du die Recordsets offen halten und warum möchtest Du nicht mit einem einzigen Recordset arbeiten?

    Was ist am anderen Ende, worauf greifst Du zu? Um Resourcen zu schonen, und um Folgefehler zu vermeiden sollten Recordsets geschlossen werden.
    Um Recourcen zu schonen und Folgefehler zu vermeiden sollten Recordsets mit Bedacht und in geringer Anzahl geöffnet werden.

    Grüße Alexander

    Freitag, 16. November 2012 15:12
  • Hallo Alexander,

    wollte nicht unhöflich sein, sorry.

    Beschreibung:

    Meine DB ist eine sehr große KursverwaltungsDB in welcher alle Daten der Teilnehmer, Kurse, Anwesenheiten, usw. gehalten werden.

    Ein Hauptformular mit einigen UF und mit VBA gesteuerten Einträgen, Verwaltungsformulare mit vielen UF, die ich per VBA aufrufe und ebenso per Doppelklick Formulare in Word und Excel ausfülle.

    Nun mehren sich in letzter Zeit die beschriebenen Fehlermeldungen und leider nicht an der gleichen Stelle. Dann Access schließen wieder aufmachen und es geht wieder.

    VBA:

    Innerhalb der Funktionen (sehr sehr viele) öffne ich ein neues Recordset, am Ende setze ich es nothing.

    Derzeit habe ich es umgeschrieben(noch nicht fertig), arbeite ein rs in einer Collection ab und fülle diese dann mit den weiteren Informationen auf, um mehrfaches Öffnen eines rs in div. Funktionen zu vermeiden.

    Deine Frage nach den Quelltext ist schwer zu erfüllen, da ich alleine 45 Module habe und fast jedes Formular VBA-Anweisungen enthält.

    Hier ein Code-Schnipsel wie ich auf die div. DB´s zugreife:

    Private Sub ColFelderBOErstellen(dat As Date)Dim sql As StringDim rs As Recordset
    Dim Anz As Integer

    Dim ID As Integer

    Dim n As String

    Dim ColZeileBO As Collection

    Dim i As Integer

        Set colFelder = New Collection

        sql = mxSQL.BOMitNameKomplett

        Set rs = mDatenbank.db.OpenRecordset(sql, dbOpenDynaset)

        Do While Not rs.EOF

            Set ColZeileBO = New Collection

            ID = rs.Fields("BO.ID")

            n = rs.Fields("BONameKomplett")

            With ColZeileBO

                .Add ID, "ID"

                .Add n, "BOName"

            End With

            colFelder.Add ColZeileBO

            rs.MoveNext

        Loop

        Set rs = Nothing

        For i = 1 To colFelder.Count

               colFelder.Item(i).Add AnzahlTNProBO(dat, CInt(colFelder.Item(i)(eBO.IDBO))), "Anzahl"

            colfelderTNErstellen i, dat

        Next i

         Set rs = Nothing

    End Sub

    In mDatenbank  initialisiere ich die DB, in mxSQL befinden sich alle SQL-Strings, bzw. Stringteile.

    Vielleicht kannst Du mir einen guten Tipp geben, wie ich die beschriebenen  Fehler verhindern kann.

    Herzlichen Dank für Deine Bemühung und nochmals sorry!

    Elisabeth


    Freitag, 16. November 2012 16:57
  • Hallo Elisabeth,
    nein den Teil mit den MaxConnections kann ich nicht sehen.
    Dieser Teil sieht sauber aus, ein Set Rs=nothing zuviel, doch das soll nicht entscheidend sein.
    Nur wozu brauchst Du die große Anzahl von Recordsets?
    Kannst Du einen Auschnitt zeigen mit :Recordset ReDim rs(MaxRsCount)?

    Grüße Alexander

    Freitag, 16. November 2012 17:39
  • Lieber Alexander!

    Herzlichen Dank für Deine prompte Antwort. Das Recordset mit ReDim habe ich noch nicht gemacht, da ich dem gegenüber etwas skeptisch war, daher auch meine Eingangsfragen.

    Wenn ich den rs neu dimensioniere betrifft das nur den erstellten rs, oder hält Access die Möglichkeit der höhere Anzahl der rs in der gesamten DB?

    Die Menge der rs entsteht, da ich die Daten aus verschiedensten Tabellen, und DB zusammenfassen muss. Bis jetzt hatte ich in einer Funktion einen rs erstellt, dann die ID in die nächste Funktion geschickt und erst am Ende alle rs wieder geschlossen. Nach massiven Auftreten dieses Problemes fülle ich Collection´s um nur einen offen zu haben, d.h. ich stopple die Daten erst in einer Collection zusammen und gebe sie erst dann aus. Das Problem hat sich aber leider nicht wesentlich geändert. 

    Ich las im Forum, dass nur 232 rs offen sein dürfen, und dies betreffe auch die auf Abfragen basierenden Formulare und Unterformulare. Könnte dort ein Problem auftreten? Ich lade beim Start einen 4 TreeView`s auf Registersteuerelement mit Namen um beim Klick-Ereignis sämtliche Daten des Kursteilnehmers darzustellen, auf diesem Form ist auch ein Button z.B. für die Verwaltung, die viele Tabelle direkt beschreibt, ebenso ein Zugang zu Anwesenheiten, wo diese unter verschiedenen Aspekten dargestellt wird. Sowohl die Anwesenheiten, als auch die Verwaltung sind natürlich zusätzlich geöffnet, werden allerdings nach dem Eintrag wieder geschlossen. 

    D.h. es könnten viele Zugriffe gleichzeitig stattfinden. Daher schien mir das ReDim eine Option. 

    Hardwaretechnisch ist alles geklärt, 8 GB Ram, Virtueller Arbeitsspeicher auf max 3072 gesetzt.

    Bin derzeit am Ende meiner Weisheit. 

    Liebe Grüße

    Elisabeth

    Freitag, 16. November 2012 20:30
  • Hallo,

    GRIDL-EDV wrote:

    1. 3-4 Frontend DB greifen permanent auf 11 Backend DB zu (auch mit VBA):
    Bekomme immer wieder folgende Fehlermeldungen: Laufzeitfehler 3048 -
    "Mehr Datenbanken können nicht geöffnet werden." und zu wenig
    Systemresourcen. Gefundene Lösung
     ConstMaxRsCount As Long=10000
     Dim rs() As Recordset
     ReDim rs(MaxRsCount)
    Gilt dies nur für den einen rs ? – Muß ich bei jeder Deklaration eines neuen rs wiederholen ?

    Die Vorgehensweise ist unueblich. Man oeffnet Recordsets, wenn man sie braucht, und schliesst sie danach wieder. Die "saubere" vorgehensweise ist:

    Dim Db As DAO.Database
    Dim Rst As DAO.Recordset
    
    Set Db = CurrentDb
    Set Rst = Db.OpenRecordset("SELECT whatever FROM wherever", dbOpenDynaset)
    Do While Not Rst.EOF
        'dein Code
        Rst.MoveNext
    Loop
    Rst.Close
    Set Rst = Nothing
    Set Db = Nothing

    Dabei ist durchaus erlaubt, innerhalb der Schleife weitere Recordsets zu
    oeffnen. Meist ist das aber nicht noetig, weil man per Aktionsabfrage
    schneller ans Ziel kommt.

    2.   Beim Schließen eines Formulars mit vielen Unterformularen werden die
    rs´s geschlossen?

    Und was passiert im Fehlerfall? Ich wuerde an deiner Stelle die
    Vorgehensweise umstellen.

    Gruss - Peter


    Mitglied im http://www.dbdev.org
    FAQ: http://www.donkarl.com

    Freitag, 16. November 2012 21:24
    Moderator
  • Hallo Peter

    Danke für deine Antwort, ich habe db nicht in der function nothing gesetzt, sondern in mDatenbank, werde ich machen, vielleicht hilft das. Im übrigen habe ich so wie du beschrieben hast das gesamte Ding programmiert, erst nach auftreten dieser Fehlermeldungen drehte ich alles um und öffnete einen rs, füllte eine Collection, schloss den rs wieder, übergab die collection und befüllte sie mit weiteren Daten. Half aber nicht wirklich, nur schneller wurde es. 

    Bei meiner 2. Frage meinte ich nicht VBA Funktionen, sondern an Abfragen gebundene Formulare und Unterformulare.

    Nochmals danke für deine Bemühungen hoffe, dass der Fehler dann weg ist. 

    LG Elisabeth

    Samstag, 17. November 2012 07:30
  • Hallo Elisabeth,

    sieh Dir 'mal diesen Thread an, vielleicht hilft der Dir weiter:

    http://social.msdn.microsoft.com/Forums/de-DE/accessde/thread/2a6b77d0-cfbb-4b0c-a738-926860ad0870

    Gruß

    Giorgio

    Montag, 19. November 2012 17:47
  • Hallo Giorgio,

    lieben Dank für Deine Bemühung, ich fürchte, dass ich es so ähnlich machen muss, da trotz Wochenendarbeit, inklusive Nacht nur eine geringe Besserung eingetreten ist. Werde Formulare komplett über vba steuer und redimen. Hoffentlich funktioniert es dann, da hier über den Test in Access 2003 gesprochen wird und meine DB läuft auf 2010.

    LG Elisabeth

    Montag, 19. November 2012 18:36
  • Hallo Elisabeth

    "GRIDL Elisabeth" schrieb

    Innerhalb der Funktionen (sehr sehr viele) öffne ich ein neues
    Recordset, am Ende setze ich es nothing.

    ..

    In mDatenbank  initialisiere ich die DB, in mxSQL befinden sich alle
    SQL-Strings, bzw. Stringteile.

    Mit den RS hat das wenig zu tun. Lies' nochmals die Fehlermeldung: "Mehr Datenbanken ...".
    Das Limit ist IIRC bei 255 Datenbanken. Da Du diese in einer eigenen Funktion zu verwalten scheinst, solltest Du diese mal herzeigen. Sonst wissen wir ja gar nicht, was Du da bastelst.

    Grundsätzlich ist es so, dass Du die Database Instanzen jeweils wieder vernichten solltest, wenn Du diese nicht mehr brauchst. Das geht aber nur, wenn Du alle Objekte, die Du darin geöffnet hast, ebenfalls schliesst und vernichtest.

    Dieser klassischer Code ohne Collection und anderes neumodisches Zeugs funktioniert problemlos:

    Dim db as Database
    Set db = CurrentDB()
    set rs1 = db.openrecordset (.....)
    set rsN = db.openrecordset (.....)
    .....
    rs1.Close
    rsN.Close
    set rs = Nothing
    set db = Nothing

    Wenn Du diesen Code verwendest, dann kannst Du sooft Du willst und aus so vielen Datenbanken wie Du willst, Recordsets öffnen. Wenn Du (z.B. aus Performance Gründen) die Datenbank Instanz lieber re-usen möchtest, dann gibt es noch den CurrentDBC Ansatz. Hier ein Beispiel, wie das gemacht werden kann:
    http://www.access-entwicklerbuch.de/2007/index.php?page=buch&bookpage=Kap_09/05.html

    Gruss
    Henry

    Dienstag, 20. November 2012 05:19
  • Hallo,

    Henry Habermacher schrieb folgendes:

    ersetzte set rs = Nothing

    aus Henrys Code noch durch:
    set rs1 = Nothing
    set rsN = Nothing

    Gruß
    Gunter


    Access FAQ: http://www.donkarl.com

          http://www.avenius.de - http://www.AccessRibbon.de
    http://www.ribboncreator.de - http://www.ribboncreator2010.de

    Dienstag, 20. November 2012 17:50
    Moderator
  • Hallo Henry,

    setze alle deklarierten rs`s am Ende der function oder sub wieder nothing und jetzt auch vorher das close. Konnte dadurch das Problem zumindest eingrenzen, aber nicht beheben. Beim Öffnen eines Zusatzformulares mit einigen Unterformularen kommt es jetzt vermehrt zu dieser Meldung. Offensichtlich muss ich die Bindung der Formulare kappen und erst beim Klickereignis ihnen den mit reDim definierten RS zuweisen.

    LG Elisabeth

    Dienstag, 20. November 2012 18:09
  • Hallo Ihr

    Hier mein Code in mDatenbank:

    Option Compare Database
    Dim mDB As Database

    Public Property Get db() As Database
        If mDB Is Nothing Then
            DatenbankInitialisieren
            Set db = mDB
        Else
            Set db = mDB
        End If
        
    End Property

    Public Property Let db(Value As Database)
        Set mDB = Value
    End Property

    Public Sub DatenbankInitialisieren()
        db = CurrentDb
    End Sub

    Public Sub RSSchließen(rs As Recordset)

        If Not rs Is Nothing Then
            rs.Close
            Set rs = Nothing
        End If
        
        If Not mDB Is Nothing Then
            Set mDB = Nothing
        End If
    End Sub

    So sind alle Function´s und Sub´s deklariert:

    Private Sub Ausstieg()
    Dim rs As Recordset
    Dim sql As String

        sql = "select * from Massnahme_Teilnehmer"
        Set rs = mDatenbank.db.OpenRecordset(sql, dbOpenDynaset)

        Do While Not rs.EOF
            If IsNull(rs.Fields("IDAustrittsStatus")) Then
                rs.Edit
                rs.Fields("IDAustrittsStatus") = 1
                rs.Update
            End If
            rs.MoveNext
        Loop
        mDatenbank.RSSchließen rs
    End Sub

    Wo ist mein Fehler ?????



    Dienstag, 20. November 2012 19:18
  • Hallo Elisabeth

    Wenn ich diesen Code anschaue wird mir schwindelig. Was bastelst Du da blos? Benutze doch einfach die Standard Vorgehensweisen, um Daten zu bearbeiten. Vezichte auf Collections und und komplizierte Ansätze um die Objekte zu initialisieren, etc. Siehe auch den Link, den ich Dir bereits geschickt hatte.

    Dann noch ein kleiner Hinweis bezüglich der letzten Funktion, die Du da aufgeführt hast:

    Private Sub Ausstieg()
    Dim rs As Recordset
    Dim sql As String

        sql = "select * from Massnahme_Teilnehmer"
        Set rs = mDatenbank.db.OpenRecordset(sql, dbOpenDynaset)

        Do While Not rs.EOF
            If IsNull(rs.Fields("IDAustrittsStatus")) Then
                rs.Edit
                rs.Fields("IDAustrittsStatus") = 1
                rs.Update
            End If
            rs.MoveNext
        Loop
        mDatenbank.RSSchließen rs
    End Sub

    Sowas lässt sich einfacher und massiv effizienter über einen Bulk Update lösen, ohne ein Recoirdset sequentiell abzuarbeiten.

    Private Sub Ausstieg() Dim sql As String sql = "UPDATE Massnahme_Teilnehmer SET IDAustrittsStatus = 1 WHERE IDAustrittsStatus IS NULL" mDatenbank.db.Execute strSQL, dbFailOnError + dbSeeChanges End Sub

    Das ist wesentlich schneller und läuft in einem Wish druch. Du brauchst kein Recordset, um diesen Update auszuführen und schon gar nicht ein sequentielles Abarbeiten der Tabelle. Selbst wenn Du unbedingt sequentielle abarbeiten willst, solltest Du die WHERE Bedingung so setzen, dass Du bereits beim Instanziieren des Recordsets auf NULL prüfst.

    Und schliesslich: Ich würde auch hier nicht über das komplizierte mDatenbank Konstrukt gehen. Mach's besser konventionell und vernichte am Schluss das Database Objekt wieder.

    Gruss

    Henry

    Mittwoch, 21. November 2012 02:11
  • Hallo Henry,

    Da hast du recht, aber das ist noch immer nicht der Grund für den Fehler: Mehr Datenbanken können nicht geöffnet werden, da ich in der Funktion rs öffne und wieder schließe. Ich suche den Grund für die Fehlermeldung. Tritt derzeit beim 2. mal Öffnen eines Formulares am häufigsten auf, dieses hat 5 Unterformulare, welche ab Abfragen gebunden sind.

    ????????

    Mittwoch, 21. November 2012 05:03
  • Du bist nicht zu überzeugen, dass es hier nicht um die Recordsets, sondern um die Database Objekte handelt, gell?

    Wenn es beim zweiten Öffnen eines Formulares auftritt, das 5 UFOs hat, dann sollte es doch eigentlich möglich sein, dieses mal vom unkonventionellen Ansatz zu befreien oder dann halt im Debug Modus durch den Code durchzugehen, bis der Fehler auftritt. Wenn Du mit dem erwähnten CurrentDBC Model arbeitest, dann kann der Fehler nicht auftreten, da in diesem Fall nur genau 1 Database Instanz vorhanden ist, die immer wieder verwendet wird. Ich vermute eher, dass bei Deinem Ansatz etwas schief läuft. Beispielsweise weil Du hier:

        If mDB Is Nothing Then
            DatenbankInitialisieren
            Set db = mDB
        Else
            Set db = mDB
        End If

    keinen Error Handler verwendest. Falls die Prüfung mDB Is Nothing schiefläuft, wirst Du DatenbankInitialisieren aufrufen. Was dann passiert, kann ich nicht sagen. Du setzt dann DB() auf eine neue CurrentDB Instanz, ob die alte dabei vernichtet wird, weiss ich nicht. Evt. bleibt diese noch bestehen, weil Du darin noch Recordset Instanziiert hast.

    Also zuerst mal überall einen vernünftigen Error Handler reinmachen:

    Public/Private Function/Sub ... (...) AS ...
    On Error GoTo ProcErr
    ... Dein Code
    ProcExit:
      Exit Sub/Function
    ProcErr:
      MsgBox "Fehler " & Err.Number & ": " & Err.Description
      Resume ProcExit
    End Function/Sub

    Wenn dann ein Fehler auftritt, findest Du heraus, wo der Auslöser ist.

    Und nochmals: Komm' weg von Deinem unkonventionellen Ansatz. Vergiss' all das Zeugs in mDatenbank mit Properties und solchen Dingen. Verwende den konventionellen oder den CurrentDBC Ansatz und es wird keine Probleme mit dem genannten Fehler mehr geben. Ich habe wesentlich komplexere Formulare mit wesentlich mehr UFOs und komplexen verschachtelten Datenbank Zugriffen in VBA und habe diesen Fehler erst wenige male gesehen, als ich in einem Loop vergessen hatte, eine Database Instanz wieder zu vernichten oder wenn ich ein Formulare mit zu vielen Domain Aggregat Funktionen (DLookup(), DSum(), DCount(), etc.) zugepflastert hatte.

    Gruss

    Henry

    Mittwoch, 21. November 2012 06:16
  • Danke Henry, werde am Wochenende die DB umbauen und die Fehlerüberprüfung einbauen.. Hoffentlich komme ich dann der Ursache auf den Grund. 

    LG Elisabeth

    Donnerstag, 22. November 2012 04:47
  • Hallo,

    GRIDL Elisabeth wrote:

    werde am Wochenende die DB umbauen und die Fehlerüberprüfung einbauen..
    Hoffentlich komme ich dann der Ursache auf den Grund. 

    Wenn du die DB wie von Henry und mir vorgeschlagen umbaust, wird die
    Ursache nicht mehr existieren. ;-)

    Gruss - Peter


    Mitglied im http://www.dbdev.org
    FAQ: http://www.donkarl.com

    Donnerstag, 22. November 2012 10:37
    Moderator
  • Herzlichen Dank an alle, die sich um mein Problem gekümmert haben.

    Lösung gefunden: seit dem letzten Update war tatsächlich die Anzahl der Forms und Steuerelemente zu viele, umgebaut und jetzt funktioniert es.

    Gruß an alle

    Elisabeth

    Donnerstag, 20. Dezember 2012 10:51