Newsgroup: it.comp.lang.visual-basic
Titolo: [?] "Tag" su oggetto Connection (ADO)

Con alcune variabili di ambiente segnallo all'applicativo che i database
sono SQL Server da gestirsi con ADO.
Lo stesso applicativo deve però gestire alcuni file di comodo/servizio in
formato Access e/o dBase, via DAO.
Il punto è che, pur avendo tutte le Sub/Function pronte per gestire ogni
tipo di file, con DAO o con ADO, le stesse (parecchie) lavorano e si
incrociano basandosi esclusivamente sulle variabili di ambiente, quindi
tratterebbero un file che deve essere Access come se dovesse essere SQL
Server.
Che complica la cosa c'è anche il fatto che periodicamente (e
contemporaneamente) devo usare i veri files di ambiente, anche mentre, per
esempio, sto trattando un file "extra-ambiente" (che so, per vedere se vi
sono messaggi per l'operatore da altri operatori). Mi spaventa l'idea di
passare a S/F e finestre varie un segnale che dica se il tal file deve
essere trattato in un modo o nell'altro. E poi, quale file? se la stessa
finestra ne può trattare più d'uno? No, impensabile.
Pensavo di assegnare una specie di "Tag" all'oggetto ADO Connection (o DAO
Database), da aprire esplicitamente con lo strumento desiderato
indipendentemente da quel che dice l'ambiente, in modo che le varie S/F si
vadano a pescare l'informazione in questa fantomatica tag (intima
dell'oggetto) per sapere, al volo, se quel che stan facendo (essenzialmente
di recordset) su quell'oggetto "base" dev'essere fatto con DAO o con ADO.
Se sono riuscito a spiegarmi, avete qualche suggerimento per inventare
questa Tag (intesa come proprietà libera, temporanea e settabile, no, non un
record fisicamente scritto) su Connection o su Database? Grazie.

Lo so che la prima cosa che mi direte è che la via più semplice è quella di
gestire ogni cosa con ADO, cambiando semplicemente la stringa di
connessione. Lo so, lo so!
Ma anche voi sapete che odio ADO e lo uso solo per SQL Server e solo perchè
sono costretto (per questo piango spesso). Vorrei quindi evitare (come la
lebbra) questa possibilità (e poi, ADO apre dBase?)

 record fisicamente scritto) su Connection o su Database? Grazie.
Giuro che non ho capito...
Quando parli di:
"avendo tutte le Sub/Function pronte per gestire ogni tipo di file" cosa
intendi?
Usi una classe di gestione che viene pilotata dall'ambiente?
Se no, perchè non usi una classe con una property che determina il
tipo di database da gestire?
...
dicci di +
...
ciao
ugo

"Lupo" chiese:
 (e poi, ADO apre dBase?)
mah, non so riguardo alle prestazioni, perň penso che tramite fonte dati
odbc possa farlo
poi penso che basterebbe provare con l'autocomposizione del controllo adodc,
per vedere se e con che stringa di connessione lavora....
poi per il resto...
[lupo] scrisse..
Lo so che la prima cosa che mi direte č che la via piů semplice č quella di
gestire ogni cosa con ADO, cambiando semplicemente la stringa di
connessione. Lo so, lo so!
Ma anche voi sapete che odio ADO e lo uso solo per SQL Server e solo perchč
sono costretto (per questo piango spesso).
direi che, a parte sql server, in effetti l'unico vantaggio di ADO sia
appunto quello di funzionare, in modo trasparente al programmatore, per
svariate fonti di dati. Sappiamo che ciň avviene a discapito delle
prestazioni, ma direi che nel caso che tu esponi nell'altro post, la scelta
di ADO sarebbe quella ufficialmente consigliata.
(lasciamo perdere i discorsi su cosa vuol dire "ufficialmente", che gli
"esperti" consigliano spesso in funzione di quello che ha deciso la mamma).
Salutoni
Sergio

 tipo di database da gestire?
Perchè quella stessa funzione, qualunque essa sia (apertura di db, di rs,
gestione, etc), può essere chiamata _anche nello stesso contesto_ da più
parti e dover trattare db diversi. Se sono tutti dello stesso tipo, vado
tranquillo, se invece, una certa procedura deve saltare da un tipo
all'altro, volevo che la tipologia/strumento fosse una "caratteristica" (la
mia "Tag") dell'oggetto Connection o Database che gli passo e loro si
scambiano.

"Lupo" scrisse:
 Sě, una serie di S/F che fanno un tot di cose e tutte (ove č necessario
 differenziare) hanno un "If Ambiente_Tal_Dei_Tali Then" che condiziona
 l'esecuzione di alcune istruzioni piuttosto che altre.
haaaaagggghhhhh, la famigerata variabile globale.... se ti sentono stavolta
sei fritto!
Salutoni
Sergio

 sei fritto!
Sarň pur fritto, ma quandocevňcevň! Con 1000 S/F che si chiamano fra di
loro, come potrei gestire gli 8000 parametri di cui ho bisogno? Se me ne
dimentico uno (o ne invento un altro), allora sě che sono davvero fritto!

 dimentico uno (o ne invento un altro), allora sì che sono davvero fritto!
è che mi sembra che tu sia proprio incappato in un errore progettuale: hai
risolto una tua esigenza (in questo caso quella di conoscere il tipo di
database con cui stai lavorando) tramite l'utilizo di una variabile globale,
cosa che poi ti ha fregato nel momento in cui l'applicazione è cresciuta e
ti sei trovato in un ambiente in cui i due tipi di database erano presenti
in contemporanea (almeno io l'ho capita così)
Non voglio atteggiarmi a maestro, però questo sembra uno dei casi da manuale
per spiegare quanto siano perniciose le variabili globali.
Per tornare al tuo problema, così, molto a volo d'uccello e senza pensare a
come la cosa sia implementabile (ho un mal di testa pazzesco), direi che
nella tua domanda c'è la risposta: una classe che, oltre alla connesione,
esponga anche la proprietà che indica il tipo di libreria utilizzato.
Ma non riesco a pensarci, a quest'ora
Salutoni
Sergio

 in contemporanea (almeno io l'ho capita cosě)
idem.
ciao
ugo

dimentico uno (o ne invento un altro), allora sě che sono davvero fritto!
Potresti definire un' interfaccia comune che singole classi
specializzate devono implementare.
Eventualmente, a monte di tutto, potresti definire una classe
costruttore che restituisce il riferimento alla classe specializzata
tramite l' interfaccia comune.  In questo modo, in tutto il resto
del programma fai sempre riferimento a detta interfaccia.
-- 
hth, hal

 detta interfaccia.
Esattamete, e la funzione costruttore restituisce l'istanza corretta a
seconda dei parametri di configurazione (variabili ambiente in questo caso,
ma anche file .ini, xml, chiave del registro, ecc...)
Ciao.
--
BSD is for UNIX lovers - linux is for Windows haters

 esponga anche la proprietà che indica il tipo di libreria utilizzato.
Non ci sono problemi importanti, ci metto niente a passare un parametro alle
varie S/F, quelle che chiamo esplicitamente da programma, che dica loro cosa
devono fare, mi ruga un po' di più che queste lo debbano ripassare alle
altre, più "nascoste" e mai esplicitamente chiamate che _loro_, a loro
volta, richiamano. Sono parecchie e non è un lavoro da 10 minuti.
Probabilmente non mi sono spiegato, ma a me pare che una proprietà che
indica il tipo di libreria presuma lo stesso lavoro. Anche perchè, come
dicevo, nello stesso istante devo poter lavorare su db di tipo diverso.
Certo, avrei dovuto pensarci prima, sarebbe stato fatto tutto con maggior
linearità, ma sai da dove sono nati i problemi? Da quando ho dovuto, alla
svelta, inserire la gestione di ADO, prima avevo solo la gestione di DAO
verso Access e anche verso SQL Server (tabelle collegate e ODBC). Da allora
ho deciso che non avrei mai più usato ADO.

 ma anche file .ini, xml, chiave del registro, ecc...)
Rispondo a entrambi, ammettendo, con estrema sincerità, di non aver capito
nulla!
Allora facciamo un esempio:
Una Sub si occupa di aprire un recordset. Sono io a chiamarla, non avrei
nessun problema a passarle un parametro che le dica di aprirlo con DAO per
Access, anche se l'ambiente dichiara ADO per SQL Server. Bene. Questa ne
chiama un'altra, autonomamente, per contare i records presenti. Quest'ultima
(salvo fare tutte le modifiche per passarle il parametro speciale) agisce
secondo quanto dichiarato in ambiente, ovvero ADO+SQL Server e, supponiamo,
sbagli tutto. Nel frattempo, in qualsasi e imprevedibile momento, scatta un
timer che attiva una sequenza di istruzioni che vanno a vedere, sugli
archivi congruenti con l'ambiente dichiarato, delle cose e per farlo
richiamo la/le stessa/e Sub prima descritta/e. Questo mi impedisce di
"imbrogliare" il sistema forzando un ambiente diverso da quello solito e
ripristinandolo quando ho finito. Io non vedo altra soluzione che prevedere
un parametro/indicatore/argomento da passare esplicitamente alle S/F
chiamate dal programma principale quando si lavora su archivi di tipo
diverso da quelli previsti dall'ambiente e (ed è questo il grosso del lavoro
che vorrei evitare) queste lo ripassano a loro volta a _tutte_ le S/F
autonomamente richiamate. A 'sto punto, se la vostra ipotesi è ancora
applicabile, devo pronunciare la frase fatidica: "si può avere un esempio?".


[cut]
Schema funzionale ( molto, _molto_ , di massima...)
classe A(constructor):
- una serie di property / sub pubbliche che pilotano il "tipo di database"
    e/o altri paramentri che ti interessano
- property get GestoreAdo() as gestoreAdo
        Set GestoreAdo = New GestoreAdo
        ...
        codice di pilotaggio della GestoreAdo per decidere il tipo di
database ecc...
        in base alle  property di cui sopra o all'ambiente al registry o
quello che preferisci...
        ...
classe B(GestoreAdo):
    - Tutte le tue brave property/sub di gestione database
    che fanno tutto quello che vuoi...
    - property get TipoDiDatabaseInUso che restituisce il tipo
    di databse impostato all'atto della creazione della classe
    o in momento diverso, in base alle tue esigenze: l'importante
    č che risulti congruente con l'effettiva connection  al database
    utilizzata nella classe.
routine applicative (bas e frm):
    - le tue routine operative, la timer di cui parli etc...
    interrogano la singola classe di gestione su cui lavorano
    e le chiedono quale tipo di databse č in uso e fanno ciň che vuoi.
Spero di aver avvicinato un po' il tuo progetto attuale alle idee
emerse fin'ora... semmai approfondiamo...
ciao
ugo

 autonomamente richiamate.
Se ho capito bene il succo del problema e' il fatto che stai lavorando
esclusivamente con routine globali, in moduli standard, e hai bisogno di
lavorare *nello stesso momento* (cioe' con catene di chiamate a sub che
possono accavallarsi) con due sistemi differenti.
Questo implica che il contesto su cui possono basarsi e' unico, ed e' dato
appunto dal tuo "ambiente" fatto di variabili globali che si diceva prima;
in questo caso temo che anche il suggerimento di hal (riassumendo credo
intendesse: creare una classe interfaccia generica IAmbiente, fornirla dei
metodi che servono, a livello di solo prototipo, quindi creare due classi
specializzate AmbienteDAO e AmbienteADO che implementano i metodi suddetti
ciascuno secondo le sue peculiarita' e fare riferimento in tutto il
programma a un generico oggetto X di tipo IAmbiente che puo' diventare di
volta in volta l'uno o l'altro) non ti risparmi il fatto di dover passare
l'istanza di X in giro per tutte le tue funzioni.
Quello che ti servirebbe, ed e' comprensibilmente un grosso lavoro di
ristrutturazione, per quanto in un certo senso "definitivo", e' di inglobare
*tutte* le tue funzioni di utilita' in una classe, in modo da poterne avere
due o piu' istanze complete a livello globale, ciascuna delle quali con un
ambiente differente, che quindi lavorano in maniera autonoma... tutte le
varie catene di chiamate avverranno sempre nell' istanza di partenza, e
quindi non hai il problema ne il problema di accavallare l'ambiente, ne
quello di doverlo passare come parametro a tutte le funzioni, in quanto
diventa proprieta' della classe.
Peraltro e' assai probabile che hal gia' intendesse questo... puoi anche
combinare le due cose (cioe' l'interfaccia come intendevo io sopra solo per
l'ambiente e la classe di funzioni con una property IAmbiente)
Non per scoraggiarti, ma qualunque soluzione tu scelga ti suggerirei di
evitare una "tapullatio precox"... prendi un bel respiro, una settimana di
tempo, e cerca di riorganizzare tutta la faccenda
Ciao
--
Luca Dormio - 
luca....@tin.it
________________________________
"Marty, non stai ragionando in maniera quadridimensionale"
Dr. Emmett L. Brown

applicabile, devo pronunciare la frase fatidica: "si può avere un esempio?".
Ti serve un oggetto o funzione costruttore che riceve, fra gli altri,
il valore di quella che adesso e' la variabile di ambiente.
Tale costruttore in base alla suddetta variabile istanzia ed 
inizializza opportunamente la classe ad hoc destinata ad
incapsulare una connessione DAO piuttosto che RDO o ADO, oppure
un recordset, collection o vattelapesca cos'altro)
Nel frattempo hai definito una o piu' interfacce che deve/ono
essere implementata/e da detta classe.
Questa interfaccia disporra' di metodi e proprieta' adeguati 
al tuo scopo, che so, Open() - Close() - GetRows() -
GetField() - FormatSystemDisk(), ecc.
La funzione costruttore, una volta istanziato ed inizializzato
l'oggetto giusto, prendera' un riferimento all'interfaccia,
che hai stabilito dover essere comune agli oggetti costruiti
da questa funzione, e restituira' proprio tale riferimento.
Il codice chiamante potra' benissimo essere all'oscuro
di quale sia la vera classe dell'oggetto ricevuto, ma
lavorera' solo con l'interfaccia comune.
Se puo' essere utile per capire meglio, pensa al tuo
codice di gestione delle stampe. Se devi produrre
un'anteprima dirigi il codice su una picturebox, mentre
se vai sulla stampante interpelli Printer.
A parte qualche dettaglio, le istruzioni sono sempre
le stesse. 
La mia gestione stampe funziona in un modo simile al tuo,
con la differenza che ho definito un' interfaccia
che mi nasconde se sto stampando su anteprima,
stampante o file o se sto salvando le informazioni
su disco con un metalinguaggio creato ad hoc
per riprodurre la stampa tutte le volte che mi
pare, in modo intero o parziale.
Analogamente, per aggiornare vecchi software da
DAO/Access-RDO/Oracle (nello stesso programma)
verso ADO, con aggiornamenti dei controlli di terze
parti, ecc. la prima cosa che ho fatto e' stato
incapsulare il codice in oggetti che emulassero
i vecchi oggetti / routines e pian piano
ho aggiornato il codice all' interno delle
nuove classi. Nel frattempo l'applicazione
doveva funzionare e risolvere i vecchi bug
che dei ladri di stipendio avevano lasciato prima di me.
Capisco che intervenire a cose fatte puo' risultare
antieconomico sul breve termine, ma, se ci sono
ragionevoli possibilita' di convenienza nel medio
termine, un pensierino ad una ristrutturazione
io ce lo farei.
-- 
ciao, hal

Desidero ringraziare tutti. Alla fine, mi pare che, a parte il metodo, ci
siamo capiti. Credo che si possa riassumere il tutto dicendo "comunque si
faccia (proprietà o parametri, etc.), è necessario un intervento importante
sul codice già presente". Ora, non certo per insistere (forse solo per
vedere se posso risparmiarmi un paio di giorni di lavoro), vorrei tornare a
bomba all'ipotesi iniziale:
Così come posso usare la proprietà Tag di un qualsiasi controllo scrivendo,
ad esempio, Text1.Tag="Pippo", vi risulta che esista (senza emularla) una
proprietà liberamente disponibile e scrivibile (senza disturbare il corretto
comportamento del tutto), sia in DAO che in ADO, con stesso nome e sintassi,
che mi consenta di scrivere oggetto_database_dao.proprieta_chimera="Pippo"
oppure oggetto_connection_ado.proprieta_chimera="Pippo"?
OK, già ci penso, usando (in ADO) lo stesso oggetto Connection per diversi
database (per risparmiare sulle licenze di SQL Server) mi ritrovo daccapo...
Boh, penso che sarò costretto a fare quanto volevo risparmiarmi...

 FormatSystemDisk(), ecc.
...ecco... questa mi manca...    ;-PPP
ciao
ugo