Newsgroup: it.comp.appl.access
Titolo: Conversione da DAO Recordset a ADODB

Salve a  tutti!
(Quello che segue è il codice di una funzione di Alessandro Baraldi
contenuta in un modulo)
---
Public Function GetDuplicato(Campo As String, _
                                                Tabella As String, _
                                                Confronto As String, _
                                                Tipo) As boolean
    Dim strCriteria As String
    Dim rs As DAO.Recordset
    strCriteria = "SELECT COUNT(*) as Duplicati FROM " & Tabella & "
WHERE "
    strCriteria = strCriteria & BuildCriteria(Campo, Tipo, Confronto)
    Set rs = CurrentDb.Openrecordset(strCriteria)
    GetDuplicato = (rs.Fields("Duplicati") <> 0)
    rs.Close
    Set rs = Nothing
End Function
---
Qualcuno mi saprebbe dire come ottenere la stessa cosa utilizzando
Recordset ADO?
(Access 2000 e successivi)
Grazie!
   Daniele.

(Access 2000 e successivi)
potresti renderla indipendente dalla libreria che usi in questo modo
----
Public Function GetDuplicato(Campo As String, _
                                                Tabella As String, _
                                                Confronto As String, _
                                                Tipo) As Boolean
    Dim strCriteria As String
    strCriteria = BuildCriteria(Campo, Tipo, Confronto)
    GetDuplicato = (DCount(Campo, Tabella, strCriteria) > 1)
End Function
----
Ciao
-- 
Giorgio Rancati
[Office Access MVP]

giorgio rancati ha scritto:

Ciao Giorgio, grazie della risposta.
Nel suo sito
(
http://www.alessandrobaraldi.it/DettaglioFaq.asp?IdFAQ=174
) Alessandro
asserisce che l'uso della funzione DCount sia meno performante rispetto
al modo da lui esposto...
Se pensi sia vero, mi aiuti a "convertire" la sua funzione?
Grazie.

 [Office Access MVP]
Ciao
@Alex

 Grazie.
Le funzione di aggregazione sono meno performanti, non lo dico io....,
ma le cose
vanno sempre pesate, se la tabella ha 10 records direi che non ha senso
farsi questi problemi...!
Il suggerimento di Giorgio è in ogni caso può risolvere il tuo
problema.
@Alex

.... cosa mi perdo...?
bo! vedendo il nome GetDuplicato ho pensato che dovesse rendere i duplicati
esistenti.


Se pensi sia vero, mi aiuti a "convertire" la sua funzione?
ma.. visto che non ho trovato nessun documento ufficiale ho voluto fare una
prova su una tabella con 128000 record.
Un ciclo di 50 ricerce richiamando la funzione GetDuplicato con DCount
impiega  10,9375  secondi, lo stesso ciclo che richiama la funzione con il
recordset set impiega  11,1875
Diminuendo il numero di record e aumentando il numero di cicli, la
differenza di tempo aumenta ma sempre in favore della funzione con DCount.
Non ho fatto la prova con un ADODB. recordset ma ho la sensazione che i
tempi si allungheranno ulteriormente.
Comunque, vista la differenza di qualche decimo di secnodo su cicli
abbastanza lunghi, ha senso dire che una è più veloce dell'altra ?


giorgio rancati ha scritto:

Non sò di cosa abbia bisogno Daniele ma lo scopo della routine è di
verificare se un dato Record è già esistente, e quella restituisce
Vero se esiste e falso se non esiste...!
@Alex

Grazie ad entrambi per la disponibilità!
Per Giorgio: Va benissimo! Stando così le cose... ovviamente la
risposta alla domanda, naturalmente, non può che essere no...
A questo punto subentra la mia curiosità personale:
mi potreste indicare una fonte in cui trovare degli esempi pratici di
come cambiano le cose da DAO a ADODB (cioè qualche esempio fatto
utilizzando DAO e riproposto ma stavolta utilizzando ADODB per chiarire
le differenze)?
Per ora sto limitandomi a sviluppare solo per Access ma... qualora in
futuro volessi implementare qualcosina anche mediante ASP... capite,
meglio essere preparati!
Ciao e grazie ancora!
   Daniele.

Vero se esiste e falso se non esiste...!
sì, ho capito cosa intendi, solo che il suo nome "GetDuplicato" mi ha fatto
pensare che dovesse rendere true se un campo ha lo stesso valore *Duplicato*
in più record.
Quando ho scritto la mia perplessità non potevo sapere cosa intendevi perchè
Daniele non aveva ancora postato il link al tuo tip.
:-)


   Daniele.
prego, ciao
Cia


 GetDuplicato = (DCount(Campo, Tabella, strCriteria) > 1)
in
GetDuplicato = (DCount(Campo, Tabella, strCriteria) > 0)
Capisco anche le perplessità di Giorgio, motivo per cui, quando l'ho
usata per i miei db, ho cambiato il nome di GetDuplicato in
"alreadyExist"; ma la sostanza non cambia, il codice è sempre quello
che originariamente hai scritto tu... per questo motivo ho preferito
non appropriarmene specificando chi era l'autore...
Un ultima cosa, non volevo mettere in dubbio la tua buona fede quando
ho chiesto a Giorgio se ritenesse vere le tue affermazioni (tant'è
vero che desideravo usare il tuo metodo convertito però ad ADODB)...
semplicemente quando non ho su che basarmi in merito a qualche
argomento, ritengo le cose corrette fino a prova contraria... mi
capisci?
Nessun rancore spero...
Ciao, grazie.
Daniele.

come cambiano le cose da DAO a ADODB
potresti partire da qui
----
Converting DAO Code to ADO [Access 2003 VBA Language Reference]
http://msdn2.microsoft.com/en-us/library/aa172265(office.11).aspx
----
e scariare questo white paper
----
"Using ADO in Microsoft Access 2002" white paper is available in Download
Center
http://support.microsoft.com/kb/301987/en-us
----


giorgio rancati ha scritto:

Grazie Giorgio, sei gentilissimo, apprezzo molto la tua disponibilità.
P.S.
Ma come riesci a calcolare i tempi (con tale precisione)?
Sono curioso, eh già! ... l'avevo detto però! (He! He!)

Sono curioso, eh giŕ! ... l'avevo detto perň! (He! He!)
ho fatto cosě, prima di inziare il ciclo memorizzi il valore della funzine
Timer()  in una variabile, poi alla fine del ciclo stampi il timer
corrente - il valore memorizzato precedentemente.
----
Sub TestGetDuplicato()
Dim i As Integer
Dim result As Boolean
Dim OldTimer As Single
OldTimer = Timer()
For i = 1 To 5000
    result = GetDuplicato("Id", "Test", "=99", dbInteger)
Next
Debug.Print Timer() - OldTimer
End Sub
----
Ciao


 [Office Access MVP]
Già... semplice ma efficace! ;-D
Ciao, grazie ancora.
   Daniele.


Ciao Giorgio. Su questa cosa ho glissato piu' di una volta con A. 
Baraldi ma ho avuto piu' volte la voglia di dire il classico "non ci 
credo neanche se lo vedo". Ho sempre pensato che le funzioni di 
aggregazione fornite da VBA fossero in qualche modo "ottimizzate" e 
comunque le ho sempre ritenute "abbastanza" interscambiabili anche se 
evito accuratamente di metterle nelle query poiche' ho notato che in 
quel caso i tempi di risposta diventano biblici.
Mi sono comunque in parte convertito alla famiglia di istruzioni della 
Dcount poiche' in quel caso il passaggio DAO / ADO e' ininfluente
-- 
ac
y-1=x

giorgio rancati ha scritto:

Non ho provato ADO in quanto era abbastanza ovvio fosse più lento.
Io ho notato questo:
Tbl=200000 records
2 Fields
   1° ID Counter
   2  Desc Testo(50) indicizzato
Con Dcount 1000 iterazioni
   For x = 1 To 1000
     ret = DCount("Progr", "T1", "Desc ='2007-500'")
   Next
  TEMPO= 1,008sec
Con DAO
   For x = 1 To 1000
     Set rs = CurrentDb.OpenRecordset("SELECT Count(*) AS DUP FROM T1
WHERE Progr='2007-500'")
     ret = rs!dup
     Set rs = Nothing
   Next
   TEMPO = 1,15 sec
praticamente conferma quanto hai visto tu..!
Poi ho fatto questo test:
QueryCompilata con predicato SQL di prima
   For x = 1 To 1000
     Set rs = CurrentDb.OpenRecordset("QRY_CMP")
     ret = rs!dup
     Set rs = Nothing
   Next
 TEMPO=0,95sec
Se non metti
Set rs=nothing
le prestazioni del RS peggiorano molto si passa a quasi 2sec...!
Ora io sono certo di aver letto diversi anni fà un articolo di un MVP
americano che addirittura proponeva le routine sostitutive a quelle di
Aggregazione sui domini proprio per ottimmizzare le prestazioni, ed a
suo tempo feci pure le prove dichiarate nell'articolo trovandomi +/-
con quanto definito dall'articolo...!
Boh ora non sò che dire, perchè le prove fatte dicono effettivamente
il contrario(anche se per un'inezia).
Di certo cerco l'articolo, sperando di trovarlo, anche per chiarezza.
Ciao Giorgio.
@Alex

 Daniele.
@Alex

 Dcount poiche' in quel caso il passaggio DAO / ADO e' ininfluente
:-)


 funzioni VBA.
e nel tuo caso ci hai mille volte dimostrato che con le Sql risolvi il 120%
-- 
-- 
Massimiliano Amendola
www.accessgroup.it
Cisa - Conferenza Italiana Sviluppatori Access

 [Office Access MVP]
Giorgio rifai i test con una Linked Table e ti stupirai....!
Mi piace sempre parlare con chi prova le cose e non con chi fa le
"SUPPOSTE"....!
Ricordavo di aver fatto i test e ti confermo che se lavori su una Local
Table quanto hai dimostrato
è vero se lavori su una Linked Table non dà scampo, e vorrei vedere
chi lavora con tabelle in locale...!
Dati test:
Iterazione su Tabella con 200000 records come sopra con 2 fields:
ID [Counter]
Desc [Testo] indicizzato
Ciclo con DCOUNT su 100 iterazioni:
TEMPO=6,5 secondi
Ciclo con il Recordet
Tempo=3,2 secondi
Ora passaimo a quanto trovato su un Sito MS:
http://office.microsoft.com/en-gb/access/HP051874531033.aspx
Improve performance of linked tables
Al paragrafo 4 spiega il motivo di questo.
;-)
@Alex

 y-1=x
Se vuoi leggi la mia risposta a Giorgio, del test fatto con le
LinkedTable, ho il Demo pronto se
vuoi fare il test sulla tua macchina...!(leggiti anche il Link MS che
ho evidenziato spiega il motivo
di questo)... Beh insomma i dati sono quelli che ho riportato.
Dopo aver fatto il test allora potrai credere o meno alla cosa.
;-)
@Alex

Al paragrafo 4 spiega il motivo di questo.
no Alessandro, il paragrafo 4 dice di non usare le funzioni DSUM() DCOUNT()
o altre funzioni VBA nelle query in ambiente MDB con tabelle collegate a Sql
Server, cosa che ho sempre consigliato (Sql server e non) di evitare come la
peste invitando a leggere il paragrafo Optimizing Queries di questa Kb
----
ACC: Optimizing for Client/Server Performance
http://support.microsoft.com/default.aspx?scid=kb;en-us;128808&Product=acc97
----
Ciao


 [Office Access MVP]
-- 
@Alex (Alessandro Baraldi)
---------------------------------------------------------------------------
http://www.sitocomune.com/
http://www.alessandrobaraldi.it
---------------------------------------------------------------------------

 ----
ho riprovato adesso, e senza cambiare nulla la cosa si è ribaltata
----
DCount 31,23438
Rs 31,95313
----
ma ripeto, si può parlare di differenze ?
se vuoi ti mando il BE e l' FE che ho usato
:-)


 [Office Access MVP]
Hai posta....!


Prova a cercare con "DCount Performances"
Alex, ognuno fa le proprie esperienze, come vedi abbiamo due risultati
completamente diversi e sinceramente senza un documento ufficiale non me la
sentirei di dire che un metodo è migliore dell'altro.
:-)


 [Office Access MVP]
-- 


 Hai posta....!
ok, anche tu.
oh.. guarda che il mio db è brutale :-)
Allega tu le due tabelle al FE, poi premi doppio click sulla "Tabella1" e
lasciala aperta, poi vai in vba ed esegui la sub TestSpeed.
Ciao


 lunghissime quando apri una semlice maschera.
Si vede che l'MVP e' straguadagnato. Interessante.
Domanda. Ed aprire un recordset e tenerlo aperto?
In genere nei miei db ho sempre una tabella con un solo record che uso 
per far fare i calcoli all'sql (l'ho chiamata Dummy o Dual ;<) )
mi verrebbe semplice usarla a questo scopo. In genere la tengo in FE ma 
se diventa funzionale la trasferisco sul BE.
Ahhhh...  e che succede quando si hanno parecchi BE? Deve esserci un 
"canale" per ciascuno di essi?
-- 
ac
y-1=x

 [Office Access MVP]
Si è brutale, ma come ti ho confermato in privato i risultati sono coerenti
con quanto evidenziato dal mio demo..., la differenza si attesta sul 20%
mediamente...!(invalidando quella con la Tabella1 chiusa).
Aspetto convalida del tuo test, che ipotizzo da te dia risultati equivalenti
ai tuoi
e questo mi turba parecchio..., quando ho rilevato i dati del tuo Test non
ci credevo
e li ho rifatti 5 volte, ma le differenze tra le 5 ripetizioni sono
assolutamente ininfluenti
e sempre differenti da quanto rilevi tu sulla tua macchina.
Cosa ipotizzi per questo...?
E' chiaro che avendo 2 macchine molto diverse il test ha una valenza molto
relativa
ma sono ugualmente molto perplesso....
Grazie come sempre per il disponibile confronto.


 Grazie come sempre per il disponibile confronto.
:-)


 [Office Access MVP]
Ciao


 "canale" per ciascuno di essi?
si, una db e una tabella aperta in ognuno di essi.
Ho iniziato a usare questo sistema quando è uscito l' OS Windows2000.
Senza quell'accorgimento stavo per perdere un cliente quando ha cambiato il
serverino con Win98 per passare a un HP con Win2000 Server.
Con Win98 mai avuto problemi, con Win2000 sever e senza BE sempre aperto, il
collegamento di 15 tabelle disposte su 4 BE, ci impiegava 15 minuti! poi una
volta collegate l'apertura delle maschere era pietosa.
Ciao


 si, una db e una tabella aperta in ognuno di essi.
aspetta.. ho riguardato la veccchia routine, io aprivo le tabelle perchè una
funzione poi mi apriva automaticamente il Db di competenza, ma basterebbe
aprire solo i databases BE.


 "canale" per ciascuno di essi?
Sě. Come ogni BE ha il suo LDB.
-- 
cu
Karl
*********
Access FAQ: 
www.donkarl.com/it
 

 da avere un campione significativo...!
e perchč no, se c'č qualcuno che vuol provare :-)
Intanto ho fatto la prova anche sul mio portatile, e il risultato č sempre
quello, a volte č piů veloce il Dcount,  a volte il Recrordset, con
differenze di 3 centesimi di secondo su un tempo totale di 10 secondi.
La prossima volta che ci vediamo te lo mostro :-)


 [Office Access MVP]
Ciao
@Alex

 e perchè no, se c'è qualcuno che vuol provare :-)
Io mi offrirei disponibile...
Che materiale mi occorrerebbe (database, ...)? Potreste fornirmelo voi?
Attualmente lavoro solo in locale ma ho a disposizione 3 PC connessi in
rete (piccola LAN domestica)... cosa devo fare per effettuare test in
remoto?
Ciao,
  Daniele.
P.S.
Che sia il caso di aprire una nuova discussione appositamente per
questo?

. ed ovviamente non è nulla sul piano personale.
Ovviamente :-)
comunque cerdo che un dato in comune lo abbiamo trovato, il Dcount è più
veloce di un ADODB.recordset con o senza indici sulla tabella
Puoi confermare ?


 la tua valutazione o la mia non importa.
Questo solo in un sistema euclideo.
Altrimenti che faccia 2 e' solo una delle tante probabilita'.
-- 
ac
y-1=x

 [Office Access MVP]
Ciao
@Alex

lo completo e lo Pubblico per avere ritorni utili.
Certo che lo trovo valido, poi ho appena detto che da gli stessi risultati
del mio :-)
Comunque tutto questo discorso a mio parere è puramente accademico, nessuno
si accorgerebbe della differenza di pochi millisecondi tra Dlookup e
Recordset quando esegue la tua funzione GetDuplicato, sia con indici che
senza.
:-)


 [Office Access MVP]
@Alex