Newsgroup: it.comp.lang.visual-basic
Titolo: [ADO] Passare connessioni aperte come parametro

Mi si è verificato il seguente problema:
Ho due funzioni contenute in una dll ActiveX registrata
in Win2000 come oggetto COM, la dichiarazione è tipo
la seguente:
public function f2(byval mycnt as adodb.connection) as variant()
dim myrs as adodb.recordset
set myrs=funzioneaprirecordset(mysql,mycnt)
end function
public function f1(byval mycnt as adodb.connectio) as variant()
dim a as variant
a=f2(mycnt)
end function
(funzione apri recordset è a sua volta in una dll active x e si occupa di
aprire un set di dati
e restituirlo)
io da programma richiamo:
output=f1(mycnt)
l'errore si genera
quando f1 richiama f2 e questa prova ad aprire il recordset
l'errore è il seguente:
"Errore di runtime '3001':
Arguments are of the wrong type, are out of acceptable range, or are in
conflict with one another"
l'errore non si genera se mycnt la apro dentro f1 invece che
nell'applicazione principale.
                                                    bye.

 public function f2(byval mycnt as adodb.connection) as variant()
Prova Byref anzichè Byval
Alberto

> > public function f2(byval mycnt as adodb.connection) as variant()
 > Prova Byref anzichè Byval
già provato, stesso messaggio di errore nello stesso punto.

'mysql' è di tipo corretto e correttamente valido nell'ambito di F2?
Alberto

> 'mysql' è di tipo corretto e correttamente valido nell'ambito di F2?
si è tutto corretto, perchè se myCnt la apro nella DLL e non nel programma
sia f1 che f2 terminano correttamente.

 ha scritto nel messaggio
news:a9h0ij$g48$1...@newsreader.mailgate.org...
public function f1(byval mycnt as adodb.???connectio???) as variant()
???

> public function f1(byval mycnt as adodb.???connectio???) as variant()
errore di battitura nel msg
public function f1(byval mycnt as adodb.connection) as variant()

Non so cosa dirti.
funzioneaprirecordset che parametri chiede?
MySql non so cosa sia, ma tu mi dici che è corretto;
MyCnt non vorrei che venisse gestito come stringa anzichè oggetto, visto che
lo passi ByVal.
Oppure, prova a testare che MyCnt.State dentro a F2.
Ma sei sicuro di avere già provato a mettere byref sia in F1 che in F2?
Ciao
Alberto

 Ma sei sicuro di avere già provato a mettere byref sia in F1 che in F2?
è stata la prima prova che ho fatto

 end function
E mysql?
Che cosa restituisce F2?
Credo sia il caso di postare il codice completo di F1 e F2.

 questa la provo ora
mycnt.state=1

 questa la provo ora
Aspetto con ansia.
Alberto

 Che cosa restituisce F2?
f2 mi darà un vettore di variant, comunque il problema non è questo
perchè non arrivo neanche ad assegnare i valori alla funzione
e comunque sia f1 che f2 funzionano correttamente, pechè se
la connessione la apro dentro f1 e questa la passo come parametro
ad f2 è tutto ok, l'errore si genera se la connessione la apro
nel programma, la passo aperta ad f1, che a sua volta la passa
ad f2, l'errore si genera dentro quest'ultima.

 mycnt.state=1
Cioč adstateopen, e questo va bene...
Non ho altre idee.
Prima di mycnt.state, verifica vartype di mycnt, poi leggi
mycnt.connectionstring, che sia correttamente impostata.
Se tutto č OK, prova a verificare gli altri parametri di F2.
Se scopri la soluzione, fammi sapere.
Ciao
Alberto

 apri nessun recordset
comunque nojnè una stringa,  è l'oggetto adodb.connection,
perchè riesco a leggere tutte le proprietà

 Se scopri la soluzione, fammi sapere.
continuerò a provare, comunque mi sembra di aver individuato
con certezza il problema nel passaggio parametri da programma
a dll, perchè anche se provo ad aprire un recordset in f1 ottengo lo
stesso errore.
se riesco a cavarne qualcosa ti faccio sapere.
                                    ciao e grazie per l'aiuto.

 mycnt.connectionstring, che sia correttamente impostata.
evito di postare la connectionstring, cmq è uguale a tutte le altre
di questo tipo che apro

 vartype(mycnt)=8
ovvero come dicevi prima tu è una stringa

 ovvero come dicevi prima tu è una stringa
anzi stando ad msdn è una stringa, ma ho provato a fare
la stessa operazione su un'altra connessione e il risultato
è sempre 8

 ha scritto nel messaggio
news:a9h9ha$p2k$1...@newsreader.mailgate.org...

Da me VarType(pippo), dove pippo è Adodb.Connection, mi torna 9, ossia
Object.
Come sai, Adodb.Connection può essere visto come Object o come Stringa, ma
la cosa non è del tutto indifferente. Ad esempio, passandolo come stringa
perdi parecchie informazioni, e non credo che si possa tenere aperta la
connessione.
Secondo me da qualche parte, usando byval, 'forzi' VB ad interpretare la
connection nel suo significato di stringa, e perdi il concetto di object.
Oppure da qualche parte hai dimensionato una variabile come Variant anzichè
Object, e appoggiandoti a tale variabile perdi la tipizzazione della
variabile.
Ma per verificarlo devi scandagliare il tuo applicativo, non credo si possa
trovare la soluzione in quelle poche righe postate.
Ciao
Alberto


continuo con la ricerca anche in altre funzioni
grazie ancora per l'aiuto se scopro qualcosa ti faccio saper.
                                            Ciao.

                                                     bye.
mmm...io mi concentrerei su questo
cose stupide che mi vengono in mente...c'è un qualche cavillo che ti sfugge
nella chiamata dall'applicazione
prova a invocarlo con una variabile globale...aspett...?...
a parte scusa credevo li passassi la stringa di connessione o qualche
parametro per decidere la conn da fare....li passi invece una conn già
aperta?...posso sapere che utilità hai a far ciò?invece di aprirla
direttamente dall'applicazione!(a questo punto...non è un doppione?e non
sarà qui che si pianta???)

 sarà qui che si pianta???)
io apro la connessione dall'applicazione principale e la passo già aperta
alle funzioni di cui ho bisogno, ed è qui che si blocca.
vorrei passarla aperta (perchè per ora ho cambiato e la apro nelle funzioni)
fondamentalmente perchè della connessione ne ho bisogna anche
nell'applicazione
per altri dati, così da non doverne aprire due, quello che cerco di fare è
proprio
evitare di avere due connessioni aperte contemporanemente.
                                            bye.

 ha scritto nel messaggio
news:a9hhtj$2lv$1...@newsreader.mailgate.org...
CUT
mi hanno risposto ad una domanda di circa un mese fa......sulle conn.La
conclusione era che era meglio aprirle e chiuderle alla bisogna...recupera
il post caso mai...
Scusa prima di stare a fare dll (non so eh! sto andando a braccio e non so
che ragioni hai)
mette tutte le tue funct in un bas e testa il tutto...e poi incapsula in una
dll....io credo che fai casino da qualche parte nell'app....perchè non fai
l'inverso....fatti aprire la conndalla dll e Usala nell'app!...mi sembra
anche + logico!!!

 anche + logico!!!
uso anche una funzione in una dll che mi apre la conn.
In questo caso avrei preferito la conn. aperta per il motivo
sopra spiegato, ed in più ho bisogno di una dll active x,
che come ho già detto è registrata in win2000 come oggetto
com, perchè alcune delle funzioni di questa dll (ne uso anche
altre) sono utilizzate anche da pagine ASP che vanno
a comporre l'applicazione.
cmq grazie per l'aiuto, per ora sto aprendo la connessione
non nel programma ma nella funzione che richiamo, ma
sono sempre alla ricerca dell'errore.


Sinceramente non capisco tutti i tuoi problemi.
Stai sicuramente seguendo la strada sbagliata.
1) Con le classi usare ByVal o ByRef è ASSOLUTAMENTE indifferente, poichè VB
passa comunque il puntatore, comunque usa ByRef per chiarezza.
2) Una classe NON PUò diventare una stringa! NEMMENO se passa attraverso a
Variant, poichè nel variant viene memorizzato il puntatore all'oggetto.
3) Se uno dei due punti non fosse valito il 99% dei programmi VB non
potrebbero funzionare.
Piuttosto, f1 e f2 sono nella stessa DLL?
O non la racconti tutta o ti stai perdendo nella direzione errata.
Puoi riprodurre e postare il problema in poche righe di codice e postare il
tutto in modo che si possa copiare e incollare in un progetto nuovo e
verificare?
Magari in un nuovo trhead, questo mi sembra sovraffolato :)
Ciao

 Magari in un nuovo trhead, questo mi sembra sovraffolato :)
ok, purtroppo domani non lavoro, quindi rimando tutto a giovedì,
cerco di ridurre il tutto allo stretto essenziale e lo posto.
grazie anche a te per l'aiuto.

[cut]
posto una porzione ridottissima di codice, le operazioni sui dati
sono senza senso, tanto l'errore si verifica prima
routine nell'applicazione .exe
Private Sub mnuProva_Click()
Dim myCnt As New ADODB.Connection
Dim myRs As New ADODB.Recordset
Dim a As New Issos.clsProva
Dim appoggio As Variant
Dim mySql As String
Dim i As Long
Dim miaCls As New NomeDLL.clsProva
With myCnt
    .CommandTimeout = 30
    .ConnectionTimeout = 15
    .CursorLocation = adUseServer
    .Mode = adModeRead
    .Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & DbName &
";Persist Security Info=True"
End With
mySql = "Select Param1 From Tabella1"
With myRs
    .CursorLocation = adUseServer
    .CursorType = adOpenForwardOnly
    .LockType = adLockReadOnly
    .ActiveConnection = myCnt
    .Open mySql
End With
i = 0
ReDim appVet(0)
While Not myRs.EOF
    i = i + 1
    ReDim Preserve appVet(i)
    appVet(i) = miaCls.f1(myCnt, myRs("Param1"))
Wend
myRs.Close
Set myRs = Nothing
End Sub
function nella DLL
Public Function f1(ByVal myCnt As ADODB.Connection, ByVal Param1 As Long) As
Variant
Dim myRs As New ADODB.Recordset
Dim mySql As String
Dim vetApp As Variant
Dim i As Long
mySql = "Select Codice, Importo From Tabella2 WHERE Param1 = " & Param1
With myRs
    .CursorLocation = adUseClient
    .CursorType = adOpenForwardOnly
    .LockType = adLockReadOnly
    .ActiveConnection = myCnt    <-- ERRORE
    .Open mySql
End With
ReDim vetApp(1, 0)
i = 0
While Not myRs.EOF
    i = i + 1
    ReDim Preserve vetApp(1, i)
    vetApp(0, i) = myRs("Codice")
    vetApp(1, i) = myRs("Importo") * (0.2)
    myRs.MoveNext
Wend
myRs.Close
Set myRs = Nothing
f1 = vetApp
End Function
le proprietą della classe sono le seguenti:
DataBindingBehavior = 0 - vbNone
DataSourceBehavior  = 0 - vbNone
Instancing = 5 - MultiUse
MTSTransactionMode  = 3 - UsesTransaction
Persistable = 0 - NotPersistable
La DLL compilata č registrata come componente COM
Se ti puņ essere di maggior aiuto giobedģ posso postare anche
il codice completo delle routine e delle funzioni dell'applicativo
che ora non ho sotto mano.
                                                ciao.

 Variant, poichè nel variant viene memorizzato il puntatore all'oggetto.
Adodb.Connection ha come proprietà predefinita ConnectionString. A seconda
della posizione nel codice, VB interpreta la variabile come Stringa o
Oggetto. Lo dimostra il fatto che BlackMagic ha valutato VarType(Connection)
e gli è tornato 8=stringa.
Se passi byval un Adodb.Connection, VB, che come noto cerca di interpretare
le mancate o errate tipizzazioni per aiutare i programmatori agli inizi,
crede che si intenda il passaggio di una stringa, e quindi usa la property
Get ConnectionString as String della classe Adodb.Connection, e la mette
dentro al variant di destinazione come se niente fosse.
Quando la si mette nel Recordset o nel Command, viene inserita la stringa, e
la connection viene in realtà clonata anzichè riutilizzata.
Adesso che ci penso: se BlackMagic apre la connection nell'applicativo, e la
connection arriva alla dll come stringa, Ado, all'apertura del recordset,
tenta di clonare la connection, aprendone una nuova. Se la precedente era
Exclusive (e lo scopro solo adesso :-((), l'apertura dovrebbe fallire.
Per BlackMagic: prova ad aprire la connection in maniera non esclusiva, e
sappimi dire se cambia qualcosa.
Ciao
Alberto

 e gli è tornato 8=stringa.
Il problema è senz'altro da qualche altra parte.
Ripeto: passare ByVal o ByRef una classe è irrilevante.
VB non converte una classe in stringa, a meno di non fare Stringa = Classe.
Ho anche provato per scrupolo proprio con una connection e VarType è SEMPRE
9 (object) come è giusto e normale che sia.
Anche la proprietà di default non influisce minimamente sulla cosa.
Ciao


     .ActiveConnection = myCnt    <-- ERRORE
Ma CA%%O!
Gli oggetti vanno assegnati con Set!
Po%&o mondo!
200 msg per scoprire che si fa?
Set .ActiveConnection = myCnt
Visto che la strada era sbagliata? :)
(poi magari non è l'unico errore, ma qui sicuramente non va!)
Ciao

 >     .ActiveConnection = myCnt    <-- ERRORE
Che guarda caso è il modo in cui VB utilizza il tipo stringa anzichè oggetto
:-))
Alberto

 Anche la proprietà di default non influisce minimamente sulla cosa.
E qua, come dimostra questo caso, non sono d'accordo.
Usando Set, effettivamente risolvi ogni ambiguità (nota comunque che
l'istruzione in cui viene associata la connection è stata postata alla fine,
altrimenti il discorso della conversione da oggetto a stringa l'avremmo
chiarito subito).
Il problema della mancata apertura della connection, sono sempre più
convinto fosse legata alla clonazione della connection nell'apertura del
recordset.
Aspettiamo l'esito delle prove di BlackMagic, poi ne riparliamo.
Alberto

 :-))
Convinto tu... :)
A me risulta che vada semplicemente in errore, come deve essere.
Per l'ennesima volta: solo assegnando ad una stringa la connection VB tenta
di usare la proprietà di default.
Ciao

 di usare la proprietà di default.
Oppure, giustamente, se il tipo a sx dell'uguale è un variant, ma noi i
variant non li usiamo (vero?) proprio per evitare questo tipo di problemi.
Ciao

 ha scritto nel messaggio
news:h5dv8.22788$b62.6...@news1.tin.it...

I variant io non li uso, come ho scritto in numerosi post nel passato.
Insisto invece sul discorso di prima:
Recordset.ActiveConnection=Altra_Connection
NON dà alcun errore (ovviamente se Altra_Connection è aperta), perchè usa il
polimorfismo di Ado.
Ad esempio:
Dim Conn As New ADODB.Connection
Dim Recst As New ADODB.Recordset
Conn.ConnectionString = "........"
Conn.Open
Recst.ActiveConnection = Conn
Funziona benissimo, ma se faccio
Recst.Open
mi viene creata una connection clonata dalla precedente.
Il problema di BlackMagic non è nel mancato uso di Set, che è consentito e
anzi, in certi casi, serve proprio se si vuole creare una duplicazione della
connessione, bensì nel fatto che in un caso la connessione è chiusa,
nell'altro caso non va perchè esiste già una connessione aperta, ma
Exclusive.
Alberto

[cut]
risposta complessiva :)
ho provato a seguire il consiglio di Zanna,
ovvero:
With myRs
    .CursorLocation = adUseServer
    .CursorType = adOpenForwardOnly
    .LockType = adLockReadOnly
    Set .ActiveConnection = myCnt  <-- Modifica
    .Open mySql
End With
ma l'errore persiste, (probabilmente sbagliando, ma da quando uso ADO,
ho sempre usato myRs.ActiveConnection = myCnt
e non ho mai avuto problemi)
preso dal dubbio ho testato nuovamente myCnt e myRs con
varType in questo modo:
Dim myCnt As New ADODB.Connection
Dim myRs As New ADODB.Recordset
Debug.Print VarType(myCnt) = 8
Debug.Print VarType(myRs) = 9
 ho effettuato il test subito dopo la dichiarazione, senza impostare
nessuna proprietà e non capisco perchè la varType di myCnt è 8 e
non 9, credo i problemi possano derivare da questo.
 Inoltre mi spiegate dove è che aprirei una connessione esclusiva?
perchè sinceramente non riesco a trovarlo, e se effettivamente
faccio questo è prob. che il problema sia proprio nell'apertura
 (riferito al codice postato precedentemente)
                        ciao

  (riferito al codice postato precedentemente)
E' stato un malinteso mio. Avevo letto "se qualcuno accede in maniera
esclusiva...", e chissa perchè pensavo che anche tu usassi l'accesso
esclusivo. Poi ho visto la tua connectionstring, e non mi sono corretto.
Dimentica quanto detto.
Ciao
Alberto


Effettivamente se metto il dim as new anche a me ritorna 8, mentre se metto
dim as classe mi torna 9....
A questo punto stiamo rischiando di perderci nei meandri della
tipizzazione....
Prova a seguire il tipo della variabile con TypeName(mycnt)
Ho perso il filo del discorso :-(((
Qual'è esattamente l'errore che ti dà in un caso e nell'altro?
Ciao
Alberto


sempre questo:
"Errore di runtime '3001':
Arguments are of the wrong type, are out of acceptable range, or are in
conflict with one another"
in ufficio in inglese, a casa l'errore è lo stesso, solo che in italiano :-)

 ok riprovo
risultati del test:
1)
Dim myCnt As new ADODB.Connection
Dim myRs As new ADODB.Recordset
Debug.Print VarType(myCnt) = 8
Debug.Print VarType(myRs) = 9
Debug.Print TypeName(myCnt) = Connection
Debug.Print TypeName(myRs) = Recordset
2)
Dim myCnt As ADODB.Connection
Dim myRs As ADODB.Recordset
Debug.Print VarType(myCnt) = 9
Debug.Print VarType(myRs) = 9
Debug.Print TypeName(myCnt) = Nothing <-- mi sembra giusto
Debug.Print TypeName(myRs) = Nothing
Set myCnt = New ADODB.Connection
Set myRs = New ADODB.Recordset
Debug.Print VarType(myCnt) = 8
Debug.Print VarType(myRs) = 9
Debug.Print TypeName(myCnt) = Connection
Debug.Print TypeName(myRs) = Recordset
c'č un motivo perchč nel secondo test prima del 'set new' myCnt č di tipo
9 e poi diventa 8 ?
                bye

 9 e poi diventa 8 ?
Probabilmente sě....
Ma in questo momento mi sfugge :-(((
Alberto

 sono senza senso, tanto l'errore si verifica prima
Vabbeh, ragazzi... io ci rinuncio.
Vi lascio alle vostre elucubrazioni.
Il codice che BlackMagic ha postato funziona perfettamente.
Continuo a non capire l'errore.
Poi i consigli (quelli utili) vengono anche scartati... (BM ha sempre fatto
senza il Set, e ha sempre sbagliato, che continui pure)
Una volta eliminati i variant *DEVE* funzionare se le cose stanno come BM
dice.
Un' altro avvertimento (che sono sicuro non seguirete) è di non usare *MAI*
Dim c as New MiaClasse
Ma sempre
Dim c as MiaClasse
Set c = New MiaClasse
Call c.Metodo
Set c = Nothing
Ciao
*** End Of Trhead(Zanna) ***

9 e poi diventa 8 ?
VarType _non_ e' affidabile perche' ritorna il tipo della proprieta' predefinita
dell' oggetto.
Prima della New le variabili myCnt e myRs puntano a Nothing, mentre dopo
la creazione delle istanze VarType legge il tipo di dato di ConnectionString
(= String) e Field (= Object).
-- 
ciao, hal

Anche la proprietà di default non influisce minimamente sulla cosa.
Ehm, qui non sono d' accordo ...
vedi il mio post in risposta a BlackMagic: l' ho provato prima di inviarlo ;-)
-- 
ciao, hal

 *** End Of Trhead(Zanna) ***
spero che mi rispondi per l'ultima volta,
poi non disturbo + :-)

 che problemi porta usare dim as new invece di dim e set ...= new ?
Se non dovesse rispondere Zanna...
Dim X As New Y
Alloca (New) un'istanza della classe Y e crea (Dim) un riferimento (X) a
tale istanza. Tale chiamata fa si che a runtime, ogni volta che si
invoca un metodo o si accede ad una proprieta di X, avvenga un controllo
sull'esistenza di X (ovvero sul fatto che X non sia Nothing).
Dim X as Y
Crea (Dim) un riferimento ad un'istanza della classe Y. Tale riferimento
e' pero' Nothing, una parola chiave che indica che il riferimento e' a
"nessuna istanza".
Set X = New Y
Alloca (New) un'istanza della classe Y ed assegna (=) alla variabile X
(atta a contentere un riferimento ad un'istanza della classe Y), il
riferimento all'oggetto appena allocato.
NON obbliga tale controllo quando si invoca un metodo o si accede ad una
proprietą di X.
Lokar

[cut]
(odio mailgate!!!)
grazie mille per il chiarimento!!! :-)
                                      bye