View Full Version : [VB.NET 2010] Leggere Risultato Query Access
Ciao ragazzi ! :ciapet:
Sto sviluppando un applicazione in Vb.Net che utilizza due thread separati (sfrutto il backgroundworker)
nel secondo thread (generato con il metodo do_work di bgworker) ho questo codice
<System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Elimina gli oggetti prima che siano esterni all'ambito")>
Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
'Prendo i dati da smsservergateway e li confronto con smspanel
Dim Comando_SmsGateway As New OleDbCommand
Dim Comando_SmsPanel As New OleDbCommand
Dim Adapter_SmsGateway As New OleDbDataAdapter
Dim Adapter_SmsPanel As New OleDbDataAdapter
Dim Reader_SmsGateway As OleDbDataReader
Dim Reader_SmsPanel As OleDbDataReader
Dim ANUMBER As String
Dim SMSMESSAGE As String
Dim RECEIVEDDATE As Date
Dim DEVICECODE As String
'Dim NUMERO As String
Dim EMAIL As String
Dim TESTO As String
Comando_SmsGateway.Connection = Connessione_server
Comando_SmsGateway.CommandText = "SELECT * FROM INBOX"
Comando_SmsGateway.CommandType = CommandType.Text
Adapter_SmsGateway.SelectCommand = Comando_SmsGateway
Connessione_server.Open()
Reader_SmsGateway = Comando_SmsGateway.ExecuteReader()
While Reader_SmsGateway.Read
ANUMBER = Reader_SmsGateway("ANUMBER")
DEVICECODE = Reader_SmsGateway("DEVICECODE")
SMSMESSAGE = Reader_SmsGateway("SMSMESSAGE")
RECEIVEDDATE = Reader_SmsGateway("RECEIVEDDATE")
TESTO = "Ricevuto da : " & ANUMBER & Chr(13) & "Testo : " & SMSMESSAGE & Chr(13) & "Ricevuto il : " & RECEIVEDDATE
Comando_SmsPanel.Connection = Connessione
Comando_SmsPanel.CommandText = "SELECT * FROM numeri INNER JOIN email ON email.id_email = numeri.idemail WHERE numero = @DEVICECODE"
Comando_SmsPanel.CommandType = CommandType.Text
Comando_SmsPanel.Parameters.AddWithValue("@DEVICECODE", DEVICECODE)
Adapter_SmsPanel.SelectCommand = Comando_SmsPanel
Connessione.Open()
Reader_SmsPanel = Comando_SmsPanel.ExecuteReader
Reader_SmsPanel.Read()
EMAIL = Reader_SmsPanel.Item(4)
Connessione.Close()
MessageBox.Show("Ricevuto da INBOX : " & ANUMBER & " " & DEVICECODE & " " & SMSMESSAGE & " " & RECEIVEDDATE & Chr(13) & "Risultato lettura smspanel : " & TESTO & Chr(13) & "Variabile " & EMAIL)
'InviaEmail(EMAIL, TESTO)
System.Threading.Thread.Sleep(500)
If BackgroundWorker1.CancellationPending Then
e.Cancel = True
Exit While
End If
End While
End Sub
Le connessioni vengono fatte a livello globale
comunque sia io sto impazzendo nel capire come leggere il risultato della seconda query (interna al ciclo while) ed assegnarlo alla variabile EMAIL, perchè mi da sempre un errore qui
Reader_SmsPanel = Comando_SmsPanel.ExecuteReader
l'errore è un eccezione : "Impossibile utilizzare oggetti COM separati dai relativi RCW sottostanti."
COSA DIAMINE DEVO FAR E??? :(:help: :help: :help: :help: :help: :muro: :muro: :muro: :muro: :muro: :muro: :muro:
Nessuno ha mai avuto questo problema ? :cry: :cry: :cry:
E' difficile dirti cosa esattamente non vada.
Bisognerebbe replicare abbastanza fedelmente il tuo ambiente di test, soprattutto quando si ha a che fare con il multithreading...
Io faccio solo alcune considerazioni, guardando velocemente quel codice :
1.
System.Threading.Thread.Sleep(500)
Vedere una Sleep mi fa sempre pensare che la cosa non sia stata studiata proprio bene... Spesso le Sleep vengono usate impropriamente perchè ci si aspetta che una certa cosa venga eseguita "sicuramente entro un tot di tempo", e poi arrivano le brutte sorprese...
2.
Reader_SmsPanel = Comando_SmsPanel.ExecuteReader
Reader_SmsPanel.Read()
Se ci si aspetta UN solo valore perchè fare un Reader ?!
Meglio .ExecuteScalar.
3.
Accedere ad un singolo file Access con codice Multithreaded, o comunque con comandi ADO.NET nidificati, può sempre portare a risultati inattesi, proprio a causa del fatto che Access digerisce male la concorrenza in lettura/scrittura...
E' difficile dirti cosa esattamente non vada.
Bisognerebbe replicare abbastanza fedelmente il tuo ambiente di test, soprattutto quando si ha a che fare con il multithreading...
Io faccio solo alcune considerazioni, guardando velocemente quel codice :
1.
System.Threading.Thread.Sleep(500)
Vedere una Sleep mi fa sempre pensare che la cosa non sia stata studiata proprio bene... Spesso le Sleep vengono usate impropriamente perchè ci si aspetta che una certa cosa venga eseguita "sicuramente entro un tot di tempo", e poi arrivano le brutte sorprese...
2.
Reader_SmsPanel = Comando_SmsPanel.ExecuteReader
Reader_SmsPanel.Read()
Se ci si aspetta UN solo valore perchè fare un Reader ?!
Meglio .ExecuteScalar.
3.
Accedere ad un singolo file Access con codice Multithreaded, o comunque con comandi ADO.NET nidificati, può sempre portare a risultati inattesi, proprio a causa del fatto che Access digerisce male la concorrenza in lettura/scrittura...
Ti rispondo il piu preciso possibile
Uso visual studio 2010 Ultimate con Net 4 (aggiornato a novembre 2010) , lo sleep l'ho usato solo per "Rallentare l'esecuzione" dato che utilizzo dei dati d'esempio su i due access (3-4 record a dir tanto)
Puo causare problemi? lo tolgo subito :D
2) uso reader perchè non sapevo come altro fare cioè mi spiego : il valore che mi aspetto è una EMAIL che si ricava dalla query
Comando_SmsPanel.CommandText = "SELECT * FROM numeri INNER JOIN email ON email.id_email = numeri.idemail WHERE numero = @DEVICECODE"
perciò pensavo di "leggere" il contenuto della query ma se bisogna usare executescalar , come dovrei procedere?
3) non è un unico file access ma ben due DB access diversi ovvero
la prima query
Comando_SmsGateway.CommandText = "SELECT * FROM INBOX"
viene fatta su un DB
e la seconda query
Comando_SmsPanel.CommandText = "SELECT * FROM numeri INNER JOIN email ON email.id_email = numeri.idemail WHERE numero = @DEVICECODE"
viene fatta su un altro DB
Funziona tutto alla perferzione tranne la lettura del risultato della seconda query e la successiva assegnazione di tale risultato alla variabile EMAIL .:muro: :muro: :muro: :muro: :muro: :muro: :muro: :muro: :muro:
Ho modificato questa parte di codice
ma ancora del risultato della query nessuna traccia , ma che diamine è????
While Reader_SmsGateway.Read()
INBOXID = Reader_SmsGateway("INBOXID")
ANUMBER = Reader_SmsGateway("ANUMBER")
DEVICECODE = Reader_SmsGateway("DEVICECODE")
SMSMESSAGE = Reader_SmsGateway("SMSMESSAGE")
RECEIVEDDATE = Reader_SmsGateway("RECEIVEDDATE")
TESTO = "Ricevuto da : " & ANUMBER & Chr(13) & "Testo : " & SMSMESSAGE & Chr(13) & "Ricevuto il : " & RECEIVEDDATE
Comando_SmsPanel.Connection = Connessione
Comando_SmsPanel.CommandText = "SELECT * FROM numeri INNER JOIN email ON email.id_email = numeri.idemail WHERE numero = @DEVICECODE "
Comando_SmsPanel.CommandType = CommandType.Text
Comando_SmsPanel.Parameters.AddWithValue("@DEVICECODE", DEVICECODE)
Connessione.Open()
EMAIL = Comando_SmsPanel.ExecuteNonQuery()
Connessione.Close()
MessageBox.Show("Ricevuto da INBOX : " & ANUMBER & " " & DEVICECODE & " " & SMSMESSAGE & " " & RECEIVEDDATE & Chr(13) & "Risultato lettura smspanel : " & TESTO & Chr(13) & "Variabile " & EMAIL)
'InviaEmail(EMAIL, TESTO)
'System.Threading.Thread.Sleep(500)
If BackgroundWorker1.CancellationPending Then
e.Cancel = True
Exit While
End If
End While
Nel mesagebox.show() mi mostra tutto perfetto e cambia (in modo congruo al DB) tutte le variabili ad ogni ciclo while , fatta eccezione per EMAIL che rimane sempre a 0 (con executenonquery):muro: :muro: :muro: :muro:
Durante il debug nella finestra delle "variabili locali" la variabile EMAIL rimane con valore "nothing" :muro:
2) uso reader perchè non sapevo come altro fare cioè mi spiego : il valore che mi aspetto è una EMAIL che si ricava dalla query
Comando_SmsPanel.CommandText = "SELECT * FROM numeri INNER JOIN email ON email.id_email = numeri.idemail WHERE numero = @DEVICECODE"
perciò pensavo di "leggere" il contenuto della query ma se bisogna usare executescalar , come dovrei procedere?
Allora, come già detto in precedenza, se la query restituisce sempre un valore, NON usare il DataReader.
Inizierei provando con .ExecuteScalar().
Il metodo è semplice, del tipo :
variabile = nomeCommand.ExecuteScalar().
Non entro nel merito della correttezza della query, ma vedo subito qualcosa che non quadra : perchè fai "SELECT *" se vuoi avere come risultato UNA stringa rappresentante UN indirizzo mail ?! :mbe:
Select-Star restituisce un record ( e quindi un insieme di valori ), non un valore. Tu devi estrarre un valore solo, ossia un CAMPO, perciò dovresti avere una "SELECT nomeCampoEmail".
Allora, come già detto in precedenza, se la query restituisce sempre un valore, NON usare il DataReader.
Inizierei provando con .ExecuteScalar().
Il metodo è semplice, del tipo :
variabile = nomeCommand.ExecuteScalar().
Non entro nel merito della correttezza della query, ma vedo subito qualcosa che non quadra : perchè fai "SELECT *" se vuoi avere come risultato UNA stringa rappresentante UN indirizzo mail ?! :mbe:
Select-Star restituisce un record ( e quindi un insieme di valori ), non un valore. Tu devi estrarre un valore solo, ossia un CAMPO, perciò dovresti avere una "SELECT nomeCampoEmail".
si scusa quella era la vecchia query , è SELECT email From...
Ora provo :read:
FUNZIONAAAAAAAAAAAAAAA
in parte
cioè mi spiego
While Reader_SmsGateway.Read()
INBOXID = Reader_SmsGateway("INBOXID")
ANUMBER = Reader_SmsGateway("ANUMBER")
DEVICECODE = Reader_SmsGateway("DEVICECODE")
SMSMESSAGE = Reader_SmsGateway("SMSMESSAGE")
RECEIVEDDATE = Reader_SmsGateway("RECEIVEDDATE")
TESTO = "Ricevuto da : " & ANUMBER & Chr(13) & "Testo : " & SMSMESSAGE & Chr(13) & "Ricevuto il : " & RECEIVEDDATE
Comando_SmsPanel.Connection = Connessione
Comando_SmsPanel.CommandText = "SELECT email FROM numeri INNER JOIN email ON email.id_email = numeri.idemail WHERE numero = '335******' "
Comando_SmsPanel.Parameters.AddWithValue("@DEVICECODE", DEVICECODE)
Comando_SmsPanel.CommandType = CommandType.Text
Connessione.Open()
EMAIL = Comando_SmsPanel.ExecuteScalar()
Connessione.Close()
MessageBox.Show("Ricevuto da INBOX : " & ANUMBER & " " & DEVICECODE & " " & SMSMESSAGE & " " & RECEIVEDDATE & Chr(13) & "Risultato lettura smspanel : " & TESTO & Chr(13) & "Variabile " & EMAIL)
'InviaEmail(EMAIL, TESTO)
'System.Threading.Thread.Sleep(500)
If BackgroundWorker1.CancellationPending Then
e.Cancel = True
Exit While
End If
End While
se lascio la clausola WHERE statica (ovvero senza @DEVICECODE) funziona e mi visualizza l'email ma , ovviamente, non è quello che cerco perchè il where dev 'essere dinamico
il bello che la variabile DEVICECODE cambia ad ogni ciclo ed è (come scritto sopra) congrua ai dati ... risolto un problema se ne presenta un altro :sofico: :doh:
RISOLTO , ora posto le modifiche effettuate:ciapet: :D :D :D :D :D :D :D :D :D :D
Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
'Prendo i dati da smsservergateway e li confronto con smspanel
Dim Comando_SmsGateway As New OleDbCommand
Dim Comando_SmsPanel As New OleDbCommand
Dim Adapter_SmsGateway As New OleDbDataAdapter
Dim Adapter_SmsPanel As New OleDbDataAdapter
Dim Reader_SmsGateway As OleDbDataReader
Dim ANUMBER As String
Dim SMSMESSAGE As String
Dim RECEIVEDDATE As Date
Dim DEVICECODE As String
Dim INBOXID As String
Dim EMAIL As String
Dim TESTO As String
Comando_SmsGateway.Connection = Connessione_server
Comando_SmsGateway.CommandText = "SELECT * FROM INBOX"
Comando_SmsGateway.CommandType = CommandType.Text
Adapter_SmsGateway.SelectCommand = Comando_SmsGateway
Connessione_server.Open()
Reader_SmsGateway = Comando_SmsGateway.ExecuteReader()
While Reader_SmsGateway.Read()
INBOXID = Reader_SmsGateway("INBOXID")
ANUMBER = Reader_SmsGateway("ANUMBER")
DEVICECODE = Reader_SmsGateway("DEVICECODE")
SMSMESSAGE = Reader_SmsGateway("SMSMESSAGE")
RECEIVEDDATE = Reader_SmsGateway("RECEIVEDDATE")
TESTO = "Ricevuto da : " & ANUMBER & Chr(13) & "Testo : " & SMSMESSAGE & Chr(13) & "Ricevuto il : " & RECEIVEDDATE
Comando_SmsPanel.Connection = Connessione
Comando_SmsPanel.CommandText = "SELECT email FROM numeri INNER JOIN email ON email.id_email = numeri.idemail WHERE numero = @DEVICECODE "
Comando_SmsPanel.Parameters.Add("@DEVICECODE", OleDbType.VarChar)
Comando_SmsPanel.Parameters("@DEVICECODE").Value = DEVICECODE
Comando_SmsPanel.CommandType = CommandType.Text
Connessione.Open()
'
EMAIL = Comando_SmsPanel.ExecuteScalar()
Connessione.Close()
MessageBox.Show("Ricevuto da INBOX : " & ANUMBER & " " & DEVICECODE & " " & SMSMESSAGE & " " & RECEIVEDDATE & Chr(13) & "Risultato lettura smspanel : " & TESTO & Chr(13) & "Variabile " & EMAIL)
'InviaEmail(EMAIL, TESTO)
'System.Threading.Thread.Sleep(500)
If BackgroundWorker1.CancellationPending Then
e.Cancel = True
Exit While
End If
End While
End Sub
Alla fine i bug erano
1) Dichiarazione esplicita della variabile per la clausola WHERE nella seconda query
2) utilizzo del metodo ExecuteScalar()
Ringrazio MarcoGG per le illuminazioni
AGGIUNGETELO SU FACEBOOK http://www.facebook.com/pages/MarcoGG/176216775722284 non vi costa nulla !
FUNZIONAAAAAAAAAAAAAAA
Ringrazio MarcoGG per le illuminazioni
AGGIUNGETELO SU FACEBOOK http://www.facebook.com/pages/MarcoGG/176216775722284 non vi costa nulla !
Beh, è un piacere aiutare chi ringrazia e reagisce ai post con tanto entusiasmo !
:D :D :D
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.