+ Rispondi al messaggio
Pagina 1 di 2 12 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 18

Form con subform rollback

  1. #1
    bertelli.davide non è in linea Scolaretto
    Buonasera,

    Ho creato due semplici tabelle non relazionate.
    La prima chiamata "Tabella"
    Id, Codice, Descrizione

    La seconda chiamata "SubTabella"
    Id,ParentId,Riga,Descrizione

    Sulla form_Load del form "FormMain"che contiene la sottomaschera "Sub" ho scritto:

    Option Compare Database
    Option Explicit
    
    Public wks As Workspace
    Public dbs As DAO.Database
    Private rst As DAO.Recordset
    Private recId As Long
    
    Private Sub Form_Initialize()
        Dim dts As String
        Dim wksName As String
        
        wksName = "#Workspace " & Trim(Str(Me.Hwnd)) & "#"
        Set wks = CreateWorkspace(wksName, "admin", "", dbUseJet)
        Set dbs = wks.OpenDatabase(CurrentDb.Name)
        
        If IsNull(Form_Menu.RecordId) Then
            dts = "SELECT Tabella.* FROM Tabella"
        Else
            dts = "SELECT Tabella.* FROM Tabella WHERE Id = " & Form_Menu.RecordId & ""
        End If
        
        Set rst = dbs.OpenRecordset(dts, dbOpenDynaset)
        Set Me.Recordset = rst
            
        Call Me.SubForm.Form.Form_Initialize
        
        Me.SubForm.LinkMasterFields = "Id"
        Me.SubForm.LinkChildFields = "ParentId"
        
        Me.BtnEdit.Enabled = True
        Me.BtnUndo.Enabled = False
        Me.BtnSave.Enabled = False
        
        If IsNull(Form_Menu.RecordId) Then
            Me.AllowAdditions = True
            Me.AllowEdits = False
            Me.AllowDeletions = False
            Me.DataEntry = True
        Else
            Me.AllowAdditions = False
            Me.AllowEdits = False
            Me.AllowDeletions = False
            Me.DataEntry = False
        End If
        
    End Sub
    
    Nel subForm "Sub" ho scritto:

    Option Compare Database
    Option Explicit
    
    Private dbs As DAO.Database
    Private rst As DAO.Recordset
    
    Public Sub Form_Initialize()
        Dim dts As String
    
        dts = "SELECT SubTabella.* FROM SubTabella"
        Set dbs = Me.Parent.dbs
        Set rst = dbs.OpenRecordset(dts, dbOpenDynaset)
        Set Me.Recordset = rst
    
    End Sub
    
    sull'evento Form_Dirty del FormMain:

    wks.begintrans
    
    Sul click del button Annulla:

    wks.rollback
    
    Sul FormMain tutto funziona ma nel SubForm No (Aggiorna immediatamente i record nella tabella "SubTabella"

    Cosa sbaglio?
    Esiste un'altro metodo oltre alle tabelle temporanee?

    Grazie
    Ultima modifica di AntonioG; 05-10-2021 06:45  Motivo: Tag code

  2. #2
    Ho sistemato i tag code per il codice, la prossima volta fallo tu quando posti del codice o sarò costretto a chiudere il thread
    ℹ️ Leggi di più su AntonioG ...

  3. #3
    Phil_cattivocarattere non è in linea Topo di biblioteca
    Quote Originariamente inviato da bertelli.davide Visualizza il messaggio
    Cosa sbaglio?
    Per prima cosa, essendo in questo forum, a non usare i tag CODE per racchiudere il codice: il post è di difficile lettura.
    Poi esprimi la tua necessità perché io non l'ho capita. Magari l'ho intuita ma se la scrivi chiaramente è meglio.

  4. #4
    L'avatar di @Alex
    @Alex non è in linea Moderatore Globale
    Quote Originariamente inviato da bertelli.davide Visualizza il messaggio
    Buonasera,

    ....

    Sul FormMain tutto funziona ma nel SubForm No (Aggiorna immediatamente i record nella tabella "SubTabella"

    Cosa sbaglio?
    Esiste un'altro metodo oltre alle tabelle temporanee?

    Grazie
    Non sbagli nulla, semplicemente non supporta le transazioni annidate in SubForm..., se ho capito bene la tua richiesta.
    ℹ️ Leggi di più su @Alex ...

  5. #5
    L'avatar di Max.Riservo
    Max.Riservo non è in linea Scribacchino
    'Form_Load del form Master
    
        Set mydb = CurrentDb
        
        sfilterM = Forms(mFMR.LISTForm).mFML.SearchKey
        sSql = "Select * FROM QTOU_Headers Where " & sfilterM
        Set rsM = mydb.OpenRecordset(sSql, dbOpenDynaset)
        
        ' SM Items
        sFieldC = "QT_FK_Quotation"
        sfilterC = Replace(sfilterM, Forms(mFMR.LISTForm).mFML.IdFld, sFieldC)
        sSql = "Select * From QTOU_Items WHERE " & sfilterC & " ORDER BY QT_Position ASC, ID_QuoteItem ASC"
        Set rsC = mydb.OpenRecordset(sSql, dbOpenDynaset)
        Set Me.SM_ITEMS.Form.Recordset = rsC
        Me.SM_ITEMS.LinkMasterFields = Forms(mFMR.LISTForm).mFML.IdFld
        Me.SM_ITEMS.LinkChildFields = sFieldC
        
        ' Main Form (to be associated after SM)
        Set Me.Recordset = rsM
    
        Set frmwrk = DBEngine.Workspaces(0)
        
        Select Case Nz(Me.OpenArgs, "")
        Case Is = "REPL"
            'Begin the transaction *AFTER* setting the recordset form sources
            frmwrk.BeginTrans
            mFMR.TransAct = True
        Case Else
            mFMR.TransAct = False
        End Select
    
    Riporto il mio codice che utilizzo per gestire la transazione in uno scenario Master/Detail.
    Tralasciando gli aspetti specifici della mia applicazione questi sono i passi salienti che ho dovuto implementare per permettere il funzionamento della transazione nella maschera e nella sottomaschera :
    - i form M e SM non sono associati (ovvero sono associati in fase di disegno, una volta che il form è corretto rimuovo l'associazione);
    - ovviamente i link master e child non sono impostati nel form ma vengono impostati a livello di codice
    - l'ordine con cui vengono effettuate alcune operazioni è fondamentale :
    - imposti il recordset della sottomaschera (SM)
    - imposti i linkMaster e Child della SM
    - imposti il recordset del form Master (M)
    - attivi la transazione (come ultima operazione !)

    Importante : il tutto avviene nell'evento Form_Load della maschera principale (M), nella subform non serve nulla.

    Nel form master ho il pulsante Aggiorna (che effettua il commit della transazione) e il pulsante Abbandona (che effettua il rollback della transazione)

  6. #6
    bertelli.davide non è in linea Scolaretto
    Grazie Max

    Ho modificato il codice......Meno de nada.
    Esegue la rollback sul form principale ma non sul figlio.

  7. #7
    bertelli.davide non è in linea Scolaretto
    Si Alex hai capito bene.
    Il codice che ho postato (Anche se non ho capito come dovevo postarlo) era un esempio semplificato.
    Nel progetto originale ho istanze multiple dello stesso form (e quindi subform).
    Ho Applicato, con qualche variante, un codice simile a quello postato da Max.
    Nel progetto tutto funziona in variazione di un record esistente ma se faccio la rollback su un nuovo record, nel sub form mi appare #Eliminato.

  8. #8
    L'avatar di @Alex
    @Alex non è in linea Moderatore Globale
    Se Max lo ha fatto significa che funziona, io ricordavo il problema della Transazione annidata..., ovvero che il Rollback funzionava sulla Form ma non sulla SubForm, tant'è che mi pareva ci fossero soluzioni creative di TempTable su cui basare la SubForm... ma probabilmente sbaglio...!

    Quì alcuni Link forse utili:

    https://codekabinett.com/rdumps.php?...ss-transaction

    https://www.tek-tips.com/viewthread.cfm?qid=887192
    ℹ️ Leggi di più su @Alex ...

  9. #9
    bertelli.davide non è in linea Scolaretto
    Grazie Alex
    Dal primo link ho trovato cose interessanti
    L'esempio che ho seguito lavora bene sino a quando sei in modifica di un record esistente.
    Quando cerchi di inserire un nuovo record si incasina tutto.

    Se hai altri suggerimenti da studiare.....
    Grazie

  10. #10
    L'avatar di Max.Riservo
    Max.Riservo non è in linea Scribacchino
    Confesso che ho penato per far funzionare il tutto però ho alla fine ci sono riuscito.
    Sono partito volendo usare ADO per le transazioni ma è stato un flop clamoroso e quindi ho dovuto ripiegare su DAO.

    Prerequisiti :
    - una tabella master con chiave primaria (PK)
    - una tabella child con FK relazionata alla PK.
    - quello da me realizzato si base su frontend Access2013 32b e backend MariaDB (MySQL).

    Passaggi da fare a livello di disegno :
    - ho un form master associato ad un recordset. Quando ho finito di posizionare i vari campi elimino l'associazione al recordset (effettuerò poi l'associazione tramite VBA).
    - ho un form child associato ad un recordset. Quando ho finito di posizionare i vari campi elimino l'associazione al recordset (effettuerò poi l'associazione tramite VBA).
    - includo nel form master il form child (che quindi diventa una subform). Nella subform verifico che le proprietà 'collega campi master' e 'collega campi secondari' non contengano alcun campo.
    I passaggi sopra descritti sono necessari per poter gestire i recordset nella transazione e per evitare che scattino prima gli eventi della subform rispetto a quelli del form master.

    Passaggi da fare in VBA nell'evento Form_Load (form master) :
    - creare il recordset SM aggiornabile da associare alla subform filtrando la FK al valore della PK. Il recordset DEVE essere di tipo DAO (non ADO)
    - associare il recordset SM alla subform
    - impostare i campi Master (PK) e Child (FK) della sub form (proprietà LinkMasterFields e LinkChildFields).
    - creare il recordset Master aggiornabile da associare alla form master filtrando per PK (1 solo record). Il recordset DEVE essere di tipo DAO (non ADO)
    - associare il recordset Master alla form master
    - avviare la transazione sull'oggetto workspace (nel mio caso DBEngine.Workspace(0).BeginTrans)

    Altre info :
    - nel form master ho un pulsante per aggiorna (se tutto ok effettua il committrans e chiude il form master)
    - nel form master ho un pulsante chiudi (se ci sono modifiche pendenti, in form master e/o nel subform, mi chiede se confermarle - quindi committrans oppure se abbandonarle - quindi rollback. Se non ci sono modifiche pendenti effettua comunque il rollback. Successivamente chiudo comunque il form master).
    - gli aggiornamenti (così come il rollback) nel form master e nel subform avvengono sotto un'unica transazione.
    - nel subform ho un pulsante elimina che utilizzo per eliminare il record corrente della subform

    Considerazioni sulle transazioni (DAO) :
    - una volta avviata una transazione è obbligatorio chiuderla (commit o rollback) anche se non ci sono modifiche da gestire/ripristinare
    - non esiste una proprietà che indichi se una transazione sia stata avviata (begintrans) : se serve saperlo occorre crearsi una proprietà a livello di form master. Nel mio caso io utilizzo il form master/subform sia in modalità edit (quindi con transazione) che in modalità view (quindi senza transazione) e alla chiusura del form master devo sapere se chiudere la transazione aperta oppure no

+ Rispondi al messaggio
Pagina 1 di 2 12 ultimoultimo

Potrebbero interessarti anche ...

  1. Form con subform in struttura a schede
    Da mailman_1969 nel forum Microsoft Access
    Risposte: 12
    Ultimo Post: 24-03-2021, 09:57
  2. Articolo: Form/SubForm di Navigazione e Managment
    Da @Alex nel forum Microsoft Access
    Risposte: 3
    Ultimo Post: 06-08-2014, 11:04
  3. Form e subform
    Da baggino nel forum Microsoft Access
    Risposte: 15
    Ultimo Post: 04-02-2014, 09:06
  4. Access - Form + Subform
    Da Fabio63 nel forum Microsoft Access
    Risposte: 7
    Ultimo Post: 02-10-2009, 11:10
  5. Access: Form + SubForm
    Da Elimar nel forum Microsoft Access
    Risposte: 3
    Ultimo Post: 12-03-2007, 17:55