Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

VBA DAO.recordset omzetten naar ADODB.recordset alg. functie

Pagina: 1
Acties:

  • Stefke
  • Registratie: December 2000
  • Laatst online: 21-11 18:08
Ik heb een sub geschreven die een DAO.recordset omzet naar een ADODB.recordset in het geheugen. Dat is bijv. handig om een settingstabel in het geheugen te plaatsen en vervolgens daar waarden uit te lezen (sneller op trage netwerken)

Dat werkt allemaal prima

Ik heb dus, samengevat:
code:
1
Public rstADODB as ADODB.recordset

sub/functie die recordset omzet
code:
1
2
3
4
5
6
7
8
9
10
sub TabelToMemory()

set DAO.recordset
set new rstADODB = ADODB.recordset

alle DAO.fields aanmaken in rstADODB
alle DAO.records aanmaken in rstADODB

DAO.close
end sub

functie om waarden uit te lezen
code:
1
2
3
4
5
Functie GetValue(key, veld)
Find rstADODB(id)=key
Geefwaarde = waarde van rstADODB(veld)
errorhandler:
     als rstADODB is nothing then TabelToMemory


Wat gebeurt er: als ik de functie GeeftWaarde(1, "naam") aanroep gaat deze zoeken in rstADODB, de public recordset in het geheugen en geeft mij de waarde van het veld "Naam" van ID=1
Als rstADODB nog niet bestaat (bijv. de eerste keer of om wat voor reden dan ook) dan treedt een error op. deze error triggert het aanmaken van de rstADODB. Ik hoef dus niet te zorgen dat de rstADODB gevuld is :)


Nu is de situatie dus dat ik een functie heb die de meest voorkomende DAO.recordsets probleemloos kan omzetten naar een ADODB.recordset. Ik zou deze functie graag "algemeen" willen gebruiken, maar dat kan nu niet omdat de functie TabelToMemory alléén de public recordset rstADODB kan vullen (want die wordt letterlijk ge-"set" in TabelToMemory().

Stel ik wil een andere tabel óók in het geheugen zetten, dan moet ik in deze situatie een andere public recordset declareren (rstADODB), maar ook de functie TabelToMemory kopieren en zorgen dat deze rstADODB2 aanmaakt.

Hoe kan ik dit ombouwen naar de situatie dat ik met één functie meerdere recordsets kan aanmaken, dus iets als

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Public rstSettings as ADODB.recordset
Public rstKlanten as ADODB.recordset

Public Function TabelToMemory(ADODB.recordset, SQL as string)
zet DAO.recordset(SQL)  om naar ADODB
end Function

GetValueSettings(key, veld)
zoek record in rstSettings
error: TabelToMemory(rstSettings, "select * from tblSettings")

GetValueKlanten(key, veld)
zoek record in rstKlanten
error: TabelToMemory(rstKlanten, "select * from tblKlanten")

Ik moet dus vanuit de functie GetValue iets meegeven waardoor de functie TabelToMemory wéét welke public ADODB.recordset hij moet vullen

Als ik dit doe:
code:
1
2
3
4
5
6
7
8
Public rstKLanten as ADODB.recordset

Public Function TabelToMemory(rstADODB as ADODB.recordset)
set rstADODB = new ADODB.recordset
zet DAO.recordset om naar rstADODB
end Function

Call TabelToMemory(rstKlanten, "select * from tblKlanten")

krijg ik een foutmelding

Dit werkt wel:
code:
1
2
3
4
5
6
7
8
Public rstKLanten as ADODB.recordset

Public Function TabelToMemory(rstADODB as variant)
set rstADODB = new ADODB.recordset
zet DAO.recordset om naar rstADODB
end Function

Call TabelToMemory(rstKlanten, "select * from tblKlanten")

Maar is dit de beste manier?

Ik hoop dat het een beetje duidelijk is :)

  • Lustucru
  • Registratie: Januari 2004
  • Niet online

Lustucru

26 03 2016

In plaats van gegoochel met DAO aen ADODB recordsets zou je eens kunnen kijken naar de moggelijkheid om helemaal afscheid te nemen van DAO, of de cache property van een DAO recordset, of de getrows() methode van een dao recordset en/of de diverse cursors.

En als je het toch met een of andere functie wilt doen:
code:
1
2
3
4
5
6
Function DaotoAdo(rs as dao.recordset) as ado.recordset
' accepteer een bestaande dao recordset, geinitialiseerd en wel
dim result as ado.recordset ' buffer voor het resultaat
' doe de omzetting
set DaoToAdo=result ' en geef het resultaat terug aan de aanroeper
End function

[ Voor 8% gewijzigd door Lustucru op 16-02-2013 15:33 ]

De oever waar we niet zijn noemen wij de overkant / Die wordt dan deze kant zodra we daar zijn aangeland


  • Stefke
  • Registratie: December 2000
  • Laatst online: 21-11 18:08
Lustucru schreef op zaterdag 16 februari 2013 @ 15:32:
In plaats van gegoochel met DAO aen ADODB recordsets zou je eens kunnen kijken naar de moggelijkheid om helemaal afscheid te nemen van DAO, of de cache property van een DAO recordset, of de getrows() methode van een dao recordset en/of de diverse cursors.

En als je het toch met een of andere functie wilt doen:
code:
1
2
3
4
5
6
Function DaotoAdo(rs as dao.recordset) as ado.recordset
' accepteer een bestaande dao recordset, geinitialiseerd en wel
dim result as ado.recordset ' buffer voor het resultaat
' doe de omzetting
set DaoToAdo=result ' en geef het resultaat terug aan de aanroeper
End function
Ik heb deze variant ook geprobeerd, alleen wordt de recordset dan elke keer dat ik een waarde oproep aangemaakt o.b.v. de DAO omdat het aanroepen van de functie zelf de ADODB-recordset declareert (bij elke aanroep). Of vergis ik me dan? Bij de test leek dat in ieder geval wel zo te zijn.

edit: ja oke. Als ik deze code 1x aanroep bij de start van het programma is de ADODBrecordset vervolgens beschikbaar in het geheugen en kan ik hier in werken. Even nakijken wat hier nou het probleem mee was (ik had dit nl. als eerste oplossing)
edit2: o ja..met deze oplossing wordt de recordset elke keer opnieuw aangemaakt, omdat zodra ik verwijs naar DaoToAdo als recordset (om er in te zoeken) hiermee meteen de "interne" functie van DaoToAdo ook gestart wordt (het aanmaken/vullen van de rst). Dan krijg ik dus een database-leesactie die ik wil voorkomen en die onnodig is aangezien ik weet dat de gegevens niet gewijzigd zijn.

Ik gebruik dit uitsluitend om een set redelijk statische gegevens (zoals een tabel met settings, de autorisaties van mijn zelf ontwikkelde autorisatiesysteem etc) in het geheugen te zetten - bijv. bij de start van de client - zonder verbinding met de database zodat het ophalen van deze settings niet meer afhankelijk is van de snelheid waarmee data opgehaald kan worden. Dat is voor zover ik begrijp NIET mogelijk met DAO (recordset in het geheugen wel, maar deze zal altijd verbinding met de db hebben).

Deze settings worden veelvuldig op allerlei momenten opgehaald en het telkens openen van een dataverbinding met de tabel geeft dan meetbare snelheidsverschillen (zeker op trage netwerken waar ik in de praktijk wel eens mee te maken heb, bijv. een 100Mbit netwerk met een werkelijke troughtput van <1Mb/s :F )

Uiteindelijk zou ik misschien van DAO kunnen afstappen, maar dat heeft - voor zover ik heb na kunnen vinden - eigenlijk alleen zin als ik de data op een SQL-server zet (?). Voor MSAccess-backends is DAO beter volgens die informatie.
Nu is performance op dat gebied nog niet zo'n enorm issue voor mijn databases omdat het aantal records over het algemeen beperkt blijft tot 10.000-en, maar ik zit met een grote hoeveelheid standaardfunctionaliteit die ik in de loop van de jaren verzameld heb en graag hergebruik (maar ook verbeter en efficienter probeerte maken), gebaseerd op DAO (dat zou ik langzaam om moeten bouwen)

zie bijv http://www.ozgrid.com/for...28221&p=143369#post143369


edit: ik had al een dergelijke constructie voor settings (maar die was "maatwerk" voor die tabel), maar daar is nu een tabel bijgekomen met configuratieparameters voor formulieren, én ik heb nog een serie tabellen in het autorisatiesysteem zitten die nu allemaal "connected" uitgelezen worden. Met deze algemene functie kan ik ze nu met een eenvoudige handeling "stateless" maken :)

[ Voor 16% gewijzigd door Stefke op 16-02-2013 16:35 ]