Form che si sfasciano

di il
22 risposte

22 Risposte - Pagina 2

  • Re: Form che si sfasciano

    05/11/2024 - Catafirro ha scritto:


    All'atto pratico la procedura che sto convertendo con interfaccia MySql ha funzionato per 25 anni interfacciata con un db access, non proprio il massimo in termini di affidabilità, con anche una quindicina di utenti in contemporanea e archivi di qualche centinaio di migliaia di record.

    Tralasciando i motivi di questa conversione che di fatto non compreso, i limiti di Access alla multiutenza sono ben noti e personalmente con una quindicina di utenti contemporaneamente la vedo tragica.

  • Re: Form che si sfasciano

    05/11/2024 - Catafirro ha scritto:


    Ripeto la mia gestione della multiconcorrenza, intendendo per multiconcorrenza l'accesso IN MODIFICA allo stesso record tramite form. Per lo stesso record intendo la testata con eventuali dettagli. Sia la tabella MySql sia la sua immagine access sono dotate di un campo DATETIME che viene riscritto ad ogni update. Quando l'utente vuole modificare un record il programma legge attraverso un recordset ADO e memorizza nella tabella locale i dati a quel momento, compreso il DATETIME. Quando l'utente ha fatto le sue modifiche e ha chiesto il salvataggio, dopo magari aver bevuto un bel caffè per tenersi su di morale, il programma rilegge il record da server, e se trova il DATETIME cambiato avverte che non è possibile salvare, ma che la modifica va ripetuta. Quante volte in 25 anni di funzionamento è successa una cosa del genere? Sono ancora vivo, per cui tanto spesso non credo. Il vantaggio naturalmente è che non si tiene bloccato il record a lungo, che, ripeto, potrebbe essere davvero a lungo visto che l'utente è una variabile indipendente e non prevedibile. Il blocco di un record è sempre un'operazione delicata, che può interferire con le transazioni, quindi per mia esperienza personale evito il più possibile, se riesco a gestire i dati in modo diverso. All'atto pratico la procedura che sto convertendo con interfaccia MySql ha funzionato per 25 anni interfacciata con un db access, non proprio il massimo in termini di affidabilità, con anche una quindicina di utenti in contemporanea e archivi di qualche centinaio di migliaia di record.

    Ecco, oggettivamente si tratta di una soluzione ‘interessante’, mi resta da capire quanto codice hai dovuto scrivere per questo tipo digestione. Da come la descrivi sembra che tu abbia emulato il comportamento dei recordset disconnessi di ADO.

    Anche io spesso ragiono in termini di record come di un insieme di records (1 per la testata e da 1 a molti per la/le tabella/e di dettaglio) dove voglio poter avere l'aggiornamento di tutto l'insieme di records oppure di nessuno e per questo utilizzo il form principale con le subform inserite in un controllo  a schede in abbinamento ad una transazione gestita da access. Però per poter avere la transazione che funziona come dico io (ovvero un pulsante aggiorna che effettuata il commit di tutte le modifiche e un pulsante abbandona che effettua il rollback di tutto) ho dovuto ingannare Access rimuovendo il recordsource dai vari form ed impostandolo (il recordsource + i link master/child delle subform) nell'evento Load del form principale, ma dopo aver avviato la transazione. Usando le transazioni ho riscontrato questo limite (pare non superabile) : una volta associato il recordset al subform non è possibile applicargli un filtro successivamente.

    Per quanto riguarda la (mia) migrazione a MySQL ho dovuto superare parecchi ostacoli prima di riuscirci : 

    • trovare un programma free che permettesse la migrazione di tabelle, dati, indici, relazioni e l'eventuale costruzione di trigger. Non l'ho trovato, quindi me lo sono fatto (con Access), esportando su file .sql la struttura delle tabelle, degli indici, delle relazioni e la creazione di alcuni trigger oltre che dei dati. I file creati vengono utilizzati direttamente da MySQL per la creazione ed importazione delle tabelle (e di tutto il resto).
    • decidere per il campo bool se mantenerlo valorizzato a -1 (Access style) o trasformarlo in +1 (MySQL / SQL Server style). Alla fine, pur avendo fatto una funzione che trasformava il +1 in true ho deciso di mantenere il -1 in quanto sono abituato a scrivere in VBA ‘IF campo THEN’
    • capire quale fosse il miglior terminatore di fine riga per i campi TEXT/MEMO considerando la migrazione del BE da Access (Windows) a MySQL, in realtà MariaDB, sotto Linux ma mantenendo il FE in Access (sempre Windows). Alla fine tra Linux (LF), Windows (CR+LF) e HTML (<br>) ho adottato quest'ultima
    • risolvere i crash di Access durante lo scorrimento di alcune tabelle linkate. I crash avvenivano solo e semplicemente trascinando la barra laterale per lo scorrimento dei record della tabella : quindi no codice da colpevolizzare. Questo è stato il problema che mi ha fatto vacillare e per il quale ho seriamente pensato di lasciar perdere la migrazione a MySQL. Non so ancora come ho fatto a trovare il problema comunque l'ho trovato : in alcuni records, nei campi TEXT oppure MEMO erano presenti dei caratteri ‘strani’ ovvero caratteri probabilmente copiati da descrizioni prese da internet o chissà da dove che utilizzavano set di caratteri non canonici (in alcuni casi il problema era il simbolo dell'euro in altri il simbolo ° in molti altri caratteri non stampabili). Nel mio programma di migrazione ho quindi fatto una sana pulizia di tutti quei caratteri che potevano creare problemi …
    • decidere quale driver ODBC utilizzare : quello di MySQL o quello di MariaDB. Ho optato per quello di MySQL in quanto è più performante rispetto a quello di MariaDB. Questo comunque è il punto meno impattante in quanto, se volessi avere la completa uniformità di driver / RDBMS , potrei disinstallare MariaDB e installare MySQL (diciamo che mi sono adeguato a quanto propone la mia installazione Linux che utilizza di default solo sw con licenza completamente opensource)

    Tornando al tuo problema di form che si ‘sfasciano’ e avendo capito che utilizzi (parecchio) codice VBA credo che l'unico modo per darti un (eventuale) consiglio sia quello di pubblicare, da parte tua, del codice …

  • Re: Form che si sfasciano

    Appena ho un attimo di tempo leggo bene il tuo intervento max.riservo, e ti dico la mia. Intanto avverto che ho risolto il mio problema, diciamo che l'ho bypassato, dopo aver sudato le classiche sette camicie per capire che cosa lo origina. Allora, il problema si verifica solo con le form aperte in multiistanza. Per chi è alle prime armi con Access spiego. Se da VBA voglio aprire la form “Clienti” devo usare l'istruzione

    DoCmd.OpenForm “Clienti”

    Se voglio aprire la stessa form un'altra volta, per averne due assieme, non posso usare la stessa istruzione, poiché una seconda form non viene aperta. In questo caso è necessario aprire la form con istruzioni del tipo

    Dim MyForm as Form
    Set  MyForm = New form_Clienti
    MultiForm.Add MyForm, MyForm.HWnd & ""
    Set MyForm = Nothing

    dove MultiForm è una collection.

    In questo modo posso aprire più istanze della stessa form, cosa necessaria ad esempio per avere i dati di due clienti affiancati per confronti o per copia di campi dall'uno all'altro. Ebbene, nel mio caso le form multiistanza funzionano bene finché l'applicazione rimane aperta, ma a chiusura e successiva riapertura alcune sono deteriorate, nel senso che non si aprono più. Il rimedio è aprirle in design e da lì chiedere la visualizzazione in formato form o sheet, è uguale. Così vanno a posto. Si tratta senz'altro di un bug di Access 365, quello che uso io e che usano i miei due clienti cavia presso i quali faccio i test. Purtroppo è un bug che si trascina da mesi. Come ho risolto?

    Prima di tutto ho minimizzato il problema, aprendo sempre la prima volta la form con il classico DoCmd.OpenForm, cosa che non dà problemi. Solo quando viene richiesta l'apertura della stessa form in un'altra copia, questa e le eventuali successive le apro generando un'istanza. Per far questo ho un piccolo codice:

     if CurrentProject.AllForms("Clienti").IsLoaded = False then
      DoCmd.OpenForm "Clienti"
    else
      Set  MyForm = New form_Clienti
      MultiForm.Add MyForm, MyForm.HWnd & ""
      Set MyForm = Nothing
    endif

    Durante il mio sviluppo io non ho bisogno di aprire due volte la stessa form, per cui non ho più il problema. Nel mio caso anche le form delle quali permetto la multiistanza vengono aperte con DoCmd. Per i miei clienti approfitterò della versione di riferimento dell'applicativo (database.accdb, per intendersi) presente sul server. La sua presenza è dovuta al fatto che ogni client la porta in locale ogni volta che c'è un aggiornamento di versione. Questa operazione viene fatta da un piccolo applicativo che lancia quello vero, e che prima di lanciarlo controlla la versione. Ebbene, a questo punto la copia in locale gliela farò fare sempre, anche se non c'è un aggiornamento di versione. In questo modo se l'applicativo locale si è rovinato alla chiusura perché l'utente ha aperto delle form in multiistanza, la successiva riapertura avverrà con la versione fresca presente sul server.

  • Re: Form che si sfasciano

    05/11/2024 - Antony73 ha scritto:


    Tralasciando i motivi di questa conversione che di fatto non compreso, i limiti di Access alla multiutenza sono ben noti e personalmente con una quindicina di utenti contemporaneamente la vedo tragica.

    Quando ho messo mano ad Access molti anni fa ho avuto validi motivi, non tutti dipendenti dalla mia volontà. In ogni caso con un'attenta gestione degli accessi al backend (con il sistema delle tabelle locali) sono riuscito a sopravvivere, scontando la necessità di qualche ripristino ogni tanto. Il sistema di accesso concorrente che ho descritto funziona bene, poiché viene minimizzato l'accesso al server. Rovescio della medaglia è che se per disgrazia due utenti hanno la pessima idea di lavorare sullo stesso record (nel mio caso si tratta di contratti letterari e accessori vari) quello che salva per ultimo ce l'ha nel buso. Ma per il tipo di lavoro è una situazione che si verifica molto molto di rado.

    La conversione attuale è dovuta al fatto che l'applicativo ne aveva bisogno per il mutare dei tempi, per alcune magagne di progettazione emerse negli anni e per alcune funzioni aggiuntive che mettere sul vecchio sarebbe stato complesso. Per una questione di costi si è preferito rimanere su access, e per una migliore gestione dei dati (sicurezza e velocità) si è optato per interfacciarlo con MySql.

  • Re: Form che si sfasciano

    05/11/2024 - Catafirro ha scritto:


    Set  MyForm = New form_Clienti
      MultiForm.Add MyForm, MyForm.HWnd & ""
      Set MyForm = Nothing

    E' vero che distruggi l'istanza del form e quindi (credo) che anche il suo riferimento nella collection venga rimosso ma nel dubbio io proverei a rimuovere il riferimento esplicitamente dalla collection.

    'prima della distruzione del form
    Set  MyForm = New form_Clienti
    MultiForm.Add MyForm, MyForm.HWnd & ""
    MultiForm.Remove MyForm.HWnd & ""
    Set MyForm = Nothing
    
    'oppure dopo
    Dim sHWnd as string
    Set  MyForm = New form_Clienti
    sHWnd = MyForm.HWnd & ""
    MultiForm.Add MyForm, sHWnd
    Set MyForm = Nothing
    MultiForm.Remove sHWnd

    In entrambe le modalità è probabile che tu ottenga un errore (che magari puoi intercettare e bypassare con un resume next) …

  • Re: Form che si sfasciano

    Certo, nel codice non viene riportato perché è da un'altra parte, ma quando la form si chiude viene rimosso l'elemento corrispondente nella collection. Lo si fa nell'evento ON_CLOSE della form. Lì mi sono sbizzarrito per cercare un rimedio al bug. Come si sa spesso i rimedi ai bug sono delle semplici assegnazioni inutili, ma che evidentemente resettano qualcosa in memoria compresi gli elementi che fanno emergere il bug. Ho anche spostato il codice, assegnato l'oggetto della collection a un altro oggetto per distruggerlo prima di rimuoverlo, ma niente da fare. Spero di essermela cavata con la soluzione che ho descritto.

    Noto ora. Attenzione, che il SET MyForm = Nothing non ha effetto sulla collection, l'oggetto non viene rimosso. Evidentemente l'ADD crea una copia.

  • Re: Form che si sfasciano

    05/11/2024 - Catafirro ha scritto:


    Noto ora. Attenzione, che il SET MyForm = Nothing non ha effetto sulla collection, l'oggetto non viene rimosso. Evidentemente l'ADD crea una copia.

    E' ragionevole, però il riferimento nella collection dovrebbe venir eliminato facendo il remove dalla collection stessa : mi pare di aver inteso che il remove comunque lo fai. 

    Dopo il remove del form cosa rimane nella collection?

    Alla chiusura dell'applicativo distruggi la collection?

  • Re: Form che si sfasciano

    05/11/2024 - max.riservo ha scritto:


    05/11/2024 - Catafirro ha scritto:


    Noto ora. Attenzione, che il SET MyForm = Nothing non ha effetto sulla collection, l'oggetto non viene rimosso. Evidentemente l'ADD crea una copia.

    E' ragionevole, però il riferimento nella collection dovrebbe venir eliminato facendo il remove dalla collection stessa : mi pare di aver inteso che il remove comunque lo fai. 

    Dopo il remove del form cosa rimane nella collection?

    Alla chiusura dell'applicativo distruggi la collection?

    Innanzitutto grazie per avermi ricordato che l'oggetto collection è anch'esso da distruggere alla chiusura dell'applicazione, nonostante sia vuoto dopo i remove a ogni chiusura di form. Ai tempi probabilmente non gli avevo dato peso, e in questo rifacimento, dove comunque ho messo le mani sulla routine di chiusura applicazione per distruggere i nuovi oggetti aggiunti, a questo non avevo pensato. Purtroppo non è servito a risolvere il bug, ma anch'io sono pignolo su queste cose.

    Allora, ho dato un'occhiata alle tue peripezie di migrazione a MySql, su alcune delle quali mi sono ritrovato, tipo i caratteri strani nei testi. Mi pare che l'associazione delle tabelle del server alle form ti abbia fatto penare. Io ho già avuto diverse esperienze con migrazioni a SqlServer, ormai diversi anni fa, dalle quali ho imparato che è bene rinunciare alle tabelle linkate. Anche se SqlServer può contare su un connettore teoricamente più veloce, oledb, comunque la velocità ne risente. Ho optato invece per form linkate a tabelle locali, come già ho scritto, con l'uso dei recordset ADODB per gestire lettura e scrittura da e sulle tabelle MySql. Per cui carico il record nella tabella locale tramite un recordset ADO in sola lettura, molto veloce, e scarico se necessario il record su server con un altro recordset ADO. Per quanto riguarda le interrogazioni dove sono necessari degli sheet linkati ai dati, nei casi complessi, dove devo presentare dei risultati molto elaborati preferisco usare ancora una tabella locale che riempio da codice, sempre leggendo con ADO, con tutte le elaborazioni del caso, e linkare quella allo sheet. Quando invece posso ottenere il risultato con una semplice query, uso query pass-through, delle quali modifico la stringa sql inserendo direttamente dentro il WHERE ottenuto da eventuale filtro richiesto. In sostanza ho una query su access che mi serve da promemoria, ne prendo la stringa sql, inserisco il WHERE necessario e con la stringa risultato creo al volo una query temporanea, che linko al mio sheet. Il risultato in velocità è eccellente. Ho anche provato a linkare un recordset, ma ho avuto qualche problema, che adesso non ricordo bene. Di sicuro c'era l'inconveniente che nel caso di parecchie tabelle in join con parecchi record lo sheet si riempiva di botto solo dopo che era arrivato l'intero recordset, mentre con le query pass-through i record arrivano un po' alla volta. Il che per utenti rompipalle è meglio, anche se alla fine i tempi sono analoghi.

Devi accedere o registrarti per scrivere nel forum
22 risposte