Newsgroup: it.comp.appl.access
Titolo: Scrittura su tabelle ODBC: una volta sì e una no sistematicamente

Ciao a tutti, ho appena creato un'applicazione che serve  per
permettere l'esecuzione di cicli di lavorazione in modo rapido,
facendo sì che con la semplice lettura di codici a barre dei sn
si registrino i tempi di lavorazione.
Memorizzo il dettaglio delle lavorazioni (singoli SN, chi e
quando li ha lavorati, che ciclo ha eseguito) in tabelle locali,
mentre in tabelle collegate via ODBC (SQL Server 2000) riporto il
totale, per Ordine di produzione, del tempo e delle schede lavorate.
Siccome le schede che si lavorano possono venire da più OdP,
gestisco le cose in modo da memorizzare i dati separatamente per
OdP, e quando si interrompe il lavoro registro i dati per ogni OdP.
Ho fatto prove con 3 OdP, e sistematicamente mi ha scritto nelle
tabelle ODBC i dati di due OdP e del terzo no (sempre lo stesso).
Facendolo singolarmente invece sì.
Ho provato con l'esecuzione riga per riga ma non pare essere diverso.
Non capisco che cosa possa succedere. Lavoro su dati di prova cui
accedo solo io, da una workstation Win 2000 SP4 con Access 97.
Ho provato anche da computer con Windows XP.
Nel caso di N OdP, il ciclo di scrittura nelle tabelle ODBC viene
ripetuto N volte, ma ho cura di chiudere i recordset usati e
reimpostare le variabili globali. Ho verificato dall'esecuzione
riga per riga che i valori sono corretti.
Se può essere d'aiuto, in alcune parti del codice ho dovuto 
eseguire due volta i SET dei recordset per non trovarmi con 
l'errore 3420: "oggetto non valido o non impostato", anche se 
l'esecuzione riga per riga già andava bene alla prima.
Possono esserci cause note che portino a questi problemi?
Alessio

 Possono esserci cause note che portino a questi problemi?
Secondo me dovrebbe essere un problema di programmazione.
La faccenda del SET eseguito più volte per via dell'errore 3420 suona molto
male: perchè usare un metodo così sporco?
Saluti.


Sì da qualche parte lo chiude o se lo perde in qualche bivio con if o select case e quindi non trova
-- 
-- 
MAssimiliano Amendola
www.accessgroup.it
Cisa - Conferenza Italiana Sviluppatori Access

Simone Calligaris ha scritto:

Sospetto più che lecito :)
Guarda, includo il codice usato per le doppie dichiarazioni, per 
mostrare quello che faccio; devo fare doppia dichiarazione anche 
in un altro paio di punti, ma NON per ogni SET.
If Not IsNull(Me![txtSN]) Then
    mioSQL = "SELECT SN_PSM.SN_PSM, Tabella_Impegni.NrImpegno " _
       & "FROM Tabella_Impegni INNER JOIN SN_PSM ON 
Tabella_Impegni.IDImpegno = SN_PSM.IDImpegno " _
       & "WHERE (((SN_PSM.SN_PSM)='" & Me![txtSN] & "'));"
    Set rst_SN_ODP = DBEngine(0)(0).OpenRecordset(mioSQL)
    Set rst_SN_ODP = DBEngine(0)(0).OpenRecordset(mioSQL)
    If rst_SN_ODP.BOF And rst_SN_ODP.EOF Then
       MsgBox rst_SN_ODP.RecordCount
       If rst_SN_ODP.RecordCount = 0 Then
          MsgBox "Il SN scelto non esiste!", vbCritical, "SN errato"
             GoTo uscita
             End If
       Else
'071001 - imposto altre due volte il recordset perchè dopo la 
prima i MoveFirst e MoveLast causano errore 3420 (oggetto non 
valido o non impostato).
          Set rst_SN_ODP = DBEngine(0)(0).OpenRecordset(mioSQL)
          Set rst_SN_ODP = DBEngine(0)(0).OpenRecordset(mioSQL)
          rst_SN_ODP.MoveLast
          rst_SN_ODP.MoveFirst
...eccetera...
Tengo a dire che con, l'esecuzione riga per riga, lo stesso 
codice usato in una query (con le modifiche opportune per il 
passaggio del criterio) funziona perfettamente.
Grazie, Alessio

 ...eccetera...
Non capisco per quale ragione prima di effettuare i .Move non testi .EOF()
Ser rst=db.openrecordset(strSQL)
if rst.eof()=False then
       rst.movelast
       rst.movefirst
       ........
endif
rst.close
set rst=nothing

 Non capisco per quale ragione prima di effettuare i .Move non testi .EOF()
Tale controllo è stato fatto poche righe prima, subito dopo i 
primi due SET del recordset (vedi il mio post precedente) e ha 
dato esito positivo,
If Not IsNull(Me![txtSN]) Then
    mioSQL = "SELECT SN_PSM.SN_PSM, Tabella_Impegni.NrImpegno " _
       & "FROM Tabella_Impegni INNER JOIN SN_PSM ON 
Tabella_Impegni.IDImpegno = SN_PSM.IDImpegno " _
       & "WHERE (((SN_PSM.SN_PSM)='" & Me![txtSN] & "'));"
    Set rst_SN_ODP = DBEngine(0)(0).OpenRecordset(mioSQL)
    Set rst_SN_ODP = DBEngine(0)(0).OpenRecordset(mioSQL)
    If rst_SN_ODP.BOF And rst_SN_ODP.EOF Then
quindi a questo punto il problema principale è capire perchè devo 
rifare il SET; infatti se il SET iniziale funzionasse a dovere, 
non lo dovrei ripetere altre tre volte...
no?

 Grazie, Alessio
-- 


MA ha scritto:

Ho sbagliato a mettere l'IF recordcount= 0, nel senso che è OVVIO 
che sia 0, hai ragione, ma il codice che esegue dentro tale IF 
(msgbox del RecordCount e msgbox che avvisa di SN non esistente) 
non causa certo errori ed è in accordo con il risultato, per 
fortuna :)
Ma se arriva all'else, e quindi riesce a controllare lo stato di 
EOF e BOF, come mai al primo MOVE causa l'errore 3420??
Gli IF Sono chiusi...ho messo "eccetera" per brevità ;)
e se non lo fosserò, direi che l'esecuzione si fermerebbe ben 
prima dell'errore 3420 :)


Ascolta Hal, perchè non adatti il tuo codice a una tabella di Northwind.mdb
(o versione SQL SVR), così si riesce a testarlo adeguatamente?
Non esiste che tu debba impostare più volte SET per un errore di quel
tipo...
Saluti.

 tipo...
Ok, lo adatto, lo riposto e faccio qualche prova.
Grazie!

 tipo...
Ecco fatto: ho adattato il codice affinchè verifichi che il nome 
di un prodotto inserito in una casella di testo ha una categoria 
di prodotto.
Una nota importante: chiedo scusa ma ho commesso un errore quando 
ho scritto il primo post, in quanto le tabelle interessate dal 
codice SQL in questione sono s' collegate in ODBC, ma da dei back 
end MDB (sul mio pc e non condivisi), non SQL Server (accedo 
successivamente a tabelle su SQL server).
Nel corso della routine eseguo comunque altre volte a tali 
tabelle, senza avere problemi.
Ecco il codice, che con un solo SET non dà il minimo problema (sigh):
Dim rst_SN_ODP As Recordset
Dim mioSQL As String
If Not IsNull(Me![txtSN]) Then
     mioSQL = "SELECT Prodotti.[NomeProdotto], 
Categorie.[IDcategoria], Categorie.[NomeCategoria] " _
       & "FROM Categorie INNER JOIN Prodotti ON 
Categorie.[IDcategoria] = Prodotti.[IDcategoria] " _
       & "WHERE (((Prodotti.[NomeProdotto])='" & Me![txtSN] & "'));"
    Set rst_SN_ODP = DBEngine(0)(0).OpenRecordset(mioSQL)
    If rst_SN_ODP.BOF And rst_SN_ODP.EOF Then
       MsgBox "Il SN scelto non esiste!", vbCritical, "SN errato"
       Exit Sub
    Else
       rst_SN_ODP.MoveLast
       rst_SN_ODP.MoveFirst
       MsgBox "OK, il prodotto <" & Me![txtSN] & "> appartiene 
alla categoria '" & rst_SN_ODP![NomeCategoria] & "'", , "numero 
record: " & rst_SN_ODP.RecordCount
    End If
End If


è certo che a te piace fare confusione e non pulisci il codice (mi viene il mal di testa a leggerlo)
dim db as dao.database
Dim rst as DAO.Recordset
Dim mioSQL As String
 
 If Not IsNull(Me![txtSN]) Then
mioSQL = "SELECT P.[NomeProdotto], C.[IDcategoria], C.[NomeCategoria] " _
     & "FROM Categorie as C INNER JOIN Prodotti as P ON  C.[IDcategoria] = P.[IDcategoria]  _
      & "WHERE p.NomeProdotto =" & chr(34) & Me![txtSN] & chr(34)
set db = currentdb
Set rst = db.OpenRecordset(mioSQL)
with rst
    if .eof then
        msgbox "We ciccio, non c'è"    
else
        .movelast
        msgbox "Ciccio ce ne sono " & .recordcount
    end if
end with
rs.close: set rs = nothing
db.close: set db = nothing
così funziona


 db.close: set db = nothing
Ti ringrazio MAssimiliano, ma puoi farmi capire PERCHE' funziona?
E' forse per l'uso delle variabili DAO.xxx?
Oppure per l'uso del currentDB al posto del DBEngine? Uso DBEngine da molto perchè ho 
letto che ha prestazioni superiori (ora non ritrovo il link, purtroppo)
Però, incuriosito da ciò che è venuto fuori in questa discussione, ho scoperto che MS 
consiglia CurrentDB
http://support.microsoft.com/?scid=kb%3Ben-us%3B131881&x=24&y=15
http://msdn2.microsoft.com/en-us/library/bb237861.aspx
Probabilmente, anche se uso Access 97, è il DBengine il mio problema, giusto?
Solo non capisco perchè non ci ho mai sbattuto il naso prima...

 Ti ringrazio MAssimiliano, ma puoi farmi capire PERCHE' funziona?
Specificare DAO è un retaggio del fatto che ho usato molto Axp ma la libreria DAO
e mi è rimasta come abitudine


 L'uso del with è secondo me necessario altrimenti è un casino
Non ho potuto rispondere prima perchè ho dovuto portare avanti anche altri lavori, 
comunque ho fatto ancora prove, e mi capita ancora che nonostante l'uso di
dim DB as DAO.database
set DB = currentDB,
se nel codice seguente non eseguo due volte il SET del recordset, in alcuni casi ricevo 
l'errore 3420.
Dim db As DAO.Database
Set db = CurrentDb
mioSQL = "SELECT P.[NomeProdotto], C.[IDcategoria], C.[NomeCategoria] " _
   & "FROM Categorie as C INNER JOIN Prodotti as P ON  C.[IDcategoria] = P.[IDcategoria] _
   & "WHERE p.NomeProdotto =" & chr(34) & Me![txtSN] & chr(34)
Set rst = db.OpenRecordset(mioSQL)
Set rst = db.OpenRecordset(mioSQL)
If rst.EOF Then
    MsgBox "Il SN scelto non esiste!", vbCritical, "SN errato"
Else
    rst.MoveLast
    rst.MoveFirst
end if
rst.Close
Set rst = Nothing
I valori del controllo txtSN sono sempre valori numerici di 8 caratteri, e l'errore non 
dipende dal valore inserito.
Fermando l'esecuzione all'errore, ho copiato in una query il codice SQL della variabile, e 
la query trova correttamente il valore.
Se nella gestione degli errori a quel punto invece dell'exit sub do un nuovo SET e un 
Resume, il MoveFirst viene eseguito tranquillamente.
questo mi succede anche alla prima esecuzione, quindi a variabili "vergini".
Ci può essere qualche impostazione da cambiare? o un modo diverso di eseguire queste 
operazioni?
Grazie,
Alessio