Acceptchange su singolo elemento di un datable

di il
21 risposte

Acceptchange su singolo elemento di un datable

Ho questo codice per cancellare un elemento di un datatable.
Sto cercando di applicare ACCEPTCHANGE sul solo elemento da cancellare e poter quindi  rimandare ad una successiva fase l'acceptchange sugli altri elementi modificati/aggiunti.
Sta di fatto che ricevo il seguente errore (che NON si verifica se il comando è esteso a tutto il TempDT!) : "impossibile eseguire questa operazione su una riga non presente nella tabella".
Il messaggio è chiarissimo, ma come faccio a non eliminare la riga dalla tabella se devo usare il comando delete?
Grazie per ogni vostro contributo. 

Private Sub DeleteItem_Click(sender As Object, e As EventArgs) Handles DeleteItem.Click
        opt = msg.cancellaRecord
        If opt = DialogResult.Yes Then
            Dim elemento As DataRow = tempDT.Rows(indice)
            Dim nominativo As String = elemento.Item(1)
            elemento.Delete()
            opt = MessageBox.Show("Scegli OK per rendere definitiva la cancellazione" & Environment.NewLine &
                           		   "Scegli CANCEL per rinunciare alla cancellazione ", "Scelta", MessageBoxButtons.OKCancel, MessageBoxIcon.Information)
            If opt = DialogResult.OK Then
                Try
                    cb = New OleDbCommandBuilder(da)
                    da.Update(ds, "legali")
                    elemento.AcceptChanges()
                    cm.Position = indice + 1
                    displayText(cm.Position)
                Catch ex As Exception
                    MsgBox(ex.Message)
                End Try
                ListBox1.Items.Add(nominativo & " - eliminato definitivamente")
            ElseIf opt = DialogResult.Cancel Then
                elemento.RejectChanges()
            End If
        End If
    End Sub

21 Risposte

  • Re: Acceptchange su singolo elemento di un datable

    Ciao,

    25/09/2023 - Jan ha scritto:


    Sto cercando di applicare ACCEPTCHANGE sul solo elemento da cancellare e poter quindi  rimandare ad una successiva fase l'acceptchange sugli altri elementi modificati/aggiunti.

    mmmmmmmhhh … quando richiami il metodo che io sappia, se hai 10 righe modificate non puoi accettare i cambiamenti per una sola riga:

    Metodo DataTable.AcceptChanges (System.Data) | Microsoft Learn

    quindi ti accetta le modifiche per tutte le righe che risultano modificate… esegue il commit per tutte le modifiche presenti dal precedente AcceptChangese lo stesso vale per il  RejectChanges

    Comunque è un pò che non metto mano al VB …. 'mo me so dato al C# ;-))

  • Re: Acceptchange su singolo elemento di un datable

    26/09/2023 - By65Franco ha scritto:


    mmmmmmmhhh … quando richiami il metodo che io sappia, se hai 10 righe modificate non puoi accettare i cambiamenti per una sola riga:

    [RISOLTO]

    Grazie,By65Franco. Non è però come pensi. AcceptChange e RejectChange possono agire su un solo elemento o su tutti gli elementi della tabella,come puoi verificare dal sottostante codice, che ho modificato per lo scopo che mi prefiggevo :

        Private Sub DeleteItem_Click(sender As Object, e As EventArgs) Handles DeleteItem.Click
            opt = msg.cancellaRecord
            If opt = DialogResult.Yes Then
                Dim elemento As DataRow = tempDT.Rows(indice)
                elemento.Delete()
                ListBox1.Items.Add(elemento("ragsoc1", DataRowVersion.Original) & " - deleted")
                elemento.AcceptChanges()
            End If
        End Sub

    Poi, quando voglio applicare l'acceptchange sulle restanti righe modificate e/o aggiunte , eseguo :

        Private Sub accept_Click(sender As Object, e As EventArgs) Handles accept.Click
            opt = msg.Accetta
            If opt = DialogResult.Yes Then
                cb = New OleDbCommandBuilder(da)
                da.Update(ds, "legali")
                'ds.Tables(0).AcceptChanges()       il metodo UPDATE esegue automaticamente Acceptchange
                ListBox1.Items.Clear()
            End If
        End Sub

    Ora, mi rimane da risolvere la causa che è all'origine di questa problematica e cioè accedere alle nuove posizione ordinali dei vari item  dopo aver effettuato delle cancellazioni (senza aver eseguito l'acceptchange, logicamente).

    Grazie ancora per la tua partecipazione.

  • Re: Acceptchange su singolo elemento di un datable

    26/09/2023 - Jan ha scritto:


    Ora, mi rimane da risolvere la causa che è all'origine di questa problematica e cioè accedere alle nuove posizione ordinali dei vari item  dopo aver effettuato delle cancellazioni (senza aver eseguito l'acceptchange, logicamente).

    Ok, capito bene… 

    ma mi sfugge solo quest'ultima cosa… 

    25/09/2023 - Jan ha scritto:


    …. come faccio a non eliminare la riga dalla tabella se devo usare il comando delete?

    questa cosa non la capisco …. nell'adapter quando fai il Delete ovviamente il record non lo hai più a disposizione e ritornerebbe in vita , prima del accetpchange, solo con il rejectchange. Quindi o dentro o fuori. 

    Non sapendo l'utilità che ha questa cosa sul tuo progetto, mi rimane difficile pensare ad una soluzione … potresti tenerti un clone dell'adapter che si aggiorna ricreandolo solo dopo accetpchange ? e in esso trovi sempre i records al loro posto fin quando non esegui l'accetpchange ?

    Non so, mi rimane difficile capire senza conosce lo scopo in modo da ipotizzare qualche soluzione. 

  • Re: Acceptchange su singolo elemento di un datable

    Per esempio potresti con il getChange leggere le righe che hanno lo stato Delete nel DataTable….

    Esempio:

    ' GetChanges retrieve delete rows
    Dim delRows As DataRow() = YourDataTable.GetChanges(DataRowState.Deleted)
    ' enumera delete rows
    For Each delRow As DataRow In delRows
        Dim delValue As String = delRow("YourColumnName").ToString()
        Console.WriteLine("Delete Value: " & delValue)
    Next

    Una cosa di questo tipo ti occorrerebbe? 

  • Re: Acceptchange su singolo elemento di un datable

    26/09/2023 - By65Franco ha scritto:


    …. come faccio a non eliminare la riga dalla tabella se devo usare il comando delete?

    La mia domanda è sarcastica ed è conseguenziale all'errore che ricevevo.

    Il problema che devo risolvere è questo : nel datatable hai i seguenti elementi:

    Mario

    Giovanni

    Dario

    Erminia

    Francesca

    ecc.

    Mario ha indice 0,Giovanni 1,Dario 2,Erminia 3,Francesca 4. 

    Ora, se eseguo la cancellazione del 2° elemento (Giovanni - ordinale 1) SENZA lanciare un acceptchange , il nuovo ordine (come apparirà nella dgv,per semplificare) sarà il seguente :

    Mario

    Dario

    Erminia

    Francesca

    Se cerco poi di cancellare Francesca , cancellerò  di fatto Erminia ,perchè  Giovanni è ancora nella posizione ordinale 1 (anche se marcato come deleted) e quindi l'elemento che appare 3° è in effetti 4°.

    Spero di essere stato chiaro, ma sono certo che aprirò presto un nuovo argomento per venire a capo della situazione utilizzando DataRowVersion.Original.

  • Re: Acceptchange su singolo elemento di un datable

    26/09/2023 - Jan ha scritto:


    Se cerco poi di cancellare Francesca , cancellerò  di fatto Erminia ,perchè  Giovanni è ancora nella posizione ordinale 1 (anche se marcato come deleted) e quindi l'elemento che appare 3° è in effetti 4°.

    Ovviamente dopo il delete nella datagridview l'indice di riga "Index" si aggiorna… se devi fare riferimento al record cancellato oppure a quelli da cancellare e/o aggiornare, si deve sempre usare Id chiave primaria della tabella “PK” , non puoi fare riferimento all'Index per operare poi nella tabella del database o nel dataset della datagridview…  

  • Re: Acceptchange su singolo elemento di un datable

    26/09/2023 - By65Franco ha scritto:


    Ovviamente dopo il delete nella datagridview l'indice di riga "Index" si aggiorna… se devi fare riferimento al record cancellato oppure a quelli da cancellare e/o aggiornare, si deve sempre usare Id chiave primaria della tabella “PK” , non puoi fare riferimento all'Index per operare poi nella tabella del database o nel dataset della datagridview…  

    Ciao,By65Franco. Scusami, ma cos'è la tabella PK? In ogni caso, per cancellare/modificare un elemento devo comunque fare riferimento alla sua posizione nella tabella

    Per accedere alla posizione dell'elemento tramite un valore qualsiasi (ID,Nome,ecc.) ho scritto questo codice:

        Private Sub DeleteItem_Click(sender As Object, e As EventArgs) Handles DeleteItem.Click
           opt = msg.cancellaRecord
           If opt = DialogResult.Yes Then
               Dim elemento As DataRow = tempDT.Rows(indice)
               Dim myID As Integer = elemento(0)
               Dim posizione As Integer = trovaIndice(myID)
               elemento.Delete()
               ListBox1.Items.Add(elemento("ragsoc1", DataRowVersion.Original) & " - deleted")
               'elemento.AcceptChanges()
           End If
       End Sub
       
       Function trovaIndice(ByVal ID As Integer)
            Dim elemento = tempDT.Select("id=" & ID)
            If elemento.Count > 0 Then
                indice = tempDT.Rows.IndexOf(elemento(0))
            End If
            Return indice
       End Function
       

    che funziona, ma è “pesante” come soluzione. Tutto ciò mi eviterebbe in ogni caso di applicare l'acceptchange ogni volta che effettuo una cancellazione.

    Cercherò un'altra soluzione…la vedo dura,però…

    By65Franco,grazie.

  • Re: Acceptchange su singolo elemento di un datable

    27/09/2023 - Jan ha scritto:


    che funziona…

    NO,NO,non funziona.

    L'indice restituito da indexof non considera le righe cancellate!!

  • Re: Acceptchange su singolo elemento di un datable

    Scusa ma non ti seguo quasi più….

    se stai lavorando con un dataSet, bindingSource tableAdapter e dataGridView, la questione non si pone nel momento in cui esegui :

                    BindingSource.Remove
                    TableAdapter.Update
                    dataSet.AcceptChanges

    quindi una volta rimossa la riga dal Binding si riflette l'aggiornamento sull' Adapter con l'Update per aggiornare la tabella e accettare con il Change

    in questa logica non devi fare nulla perchè i metodi fanno tutto loro e lo fanno bene.

    25/09/2023 - Jan ha scritto:


    Sto cercando di applicare ACCEPTCHANGE sul solo elemento da cancellare e poter quindi  rimandare ad una successiva fase l'acceptchange sugli altri elementi modificati/aggiunti.

    Un alternativa che non sconvolge la logica di cui sopra, può essere quella di inserire una colonna in più nella dataGridView con il Check di tipo booleano.

    A questo punto metterai la spunta sul Flag per contrassegnare che tali righe verranno eliminate

    Poi quando vuoi eseguire effettivamente la cancellazione delle righe contrassegnate, allora eseguirai una Enumerazione delle righe contrassegnate e richiamerai dopo l'EndEdit … il Remove , l'Update e l'AcceptChange.

    In questo modo non devi fare nulla di anomalo rispetto alla logica preesistente.


    In questo caso se non vuoi vedere le righe contrassegnate, se le vuoi nascondere come se fossero eliminate, sull'evento change della cella puoi filtrare la dataGridView per escludere dalla visualizzazione tali righe oppure tenerle visibili con un colore diverso e bloccate.

    Puoi predisporre messaggi di conferma e o di ripristino di tale righe per confermare di averle contrassegnate oppure per riportale in vita nella dataGridView.

    Puoi gestire l'abbandono accidentale o voluto della Form emettendo un messaggio se si vogliono abbandonare le modifiche in sospeso, sfruttando sempre i metodi preesistenti.


    Insomma, io prediligerei sempre di utilizzare metodi standard per non incappare mai in certi problemi…

  • Re: Acceptchange su singolo elemento di un datable

    27/09/2023 - Jan ha scritto:


    Scusami, ma cos'è la tabella PK?

    Dicasi PK la chiave primaria della tabella del database

    Dicasi FK la chiave esterna di relazione tra le tabelle del database

    ;-))

  • Re: Acceptchange su singolo elemento di un datable

    La questione non è complessa : ho un datatable ,il quale viene letto da un dgv.

    Se cancello uno,due elementi dal datatable con il metodo delete (senza eseguire un acceptchange) ,le posizioni ordinali si modificano e se ,quindi, cerco di cancellare quello che nella binding navigator mi viene indicato come decimo record (10/258) vado a cancellare l'ottavo elemento della datatable (giacchè il datatable contiene ancora i due elementi cancellati).

    Ora, senza applicare acceptchange, come faccio ad individuare l'esatta posizione ordinale degli elementi del datatable dopo che sono state effettuate delle cancellazioni?

    By65Franco, sono consapevole che stai facendo di tutto per aiutarmi (e di tanto te ne sono grato) e non chiedo perciò il tuo ulteriore intervento!Ti sarai annoiato!

    Ci riproverò e poi di farò sapere.Grazieeeeee.

  • Re: Acceptchange su singolo elemento di un datable

    27/09/2023 - Jan ha scritto:


    Ora, senza applicare acceptchange, come faccio ad individuare l'esatta posizione ordinale degli elementi del datatable dopo che sono state effettuate delle cancellazioni?

    Devi necessariamente fare l acceptchange  come ti dicevo in precedenza 

    Ma non capisco cosa hai combinato con il dgv e il datatable che non sono più allineati … perché è di molto strano che l’indice di riga del dgv non corrisponda piu al record effettivo … anche se non fai il acceptchange devono sempre corrispondere. 

    Però dovrai ridere come stai gestendo questo flusso, stai interrompendo una logica dove i records della tabella si devono riflettere a catena e tu la stai interrompendo e vorresti che funzionasse comunque… questo non è possibile. 

    È’ evidente che il dgv è azzoppato rispetto al dataTable in caso di eliminazione di una riga e le conseguenze sono quelle che segnali. Quindi l’operazione di eliminazione si deve riflettere nei sottostanti altrimenti se non si conclude l’operazione, rimarrai sempre disallineato e l’indice di riga non coinciderà mai con il record effettivo. 

  • Re: Acceptchange su singolo elemento di un datable

    27/09/2023 - By65Franco ha scritto:


    Ma non capisco cosa hai combinato con il dgv e il datatable che non sono più allineati … perché è di molto strano che l’indice di riga del dgv non corrisponda piu al record effettivo … anche se non fai il acceptchange devono sempre corrispondere

    DVG e datatable non sono più allineati dopo le cancellazioni.

    Grazie comunque per ogni tuo gradito intervento.

    Abbandono definitivamente la gestione tramite datatable e passo a dataview, che non presenta lo stesso problema dopo il delete.

  • Re: Acceptchange su singolo elemento di un datable

    28/09/2023 - Jan ha scritto:


    Abbandono definitivamente la gestione tramite datatable e passo a dataview, che non presenta lo stesso problema dopo il delete.

    Per esperienza in passato in Vb e adesso sul C#, ti posso confermare che se usi bene e approfondisci altrettanto… 
    con un DataSet che espone le tabelle del database 
    un tableAdapter
    un bindingSource 

    arrivi agevolmente al 99% della programmazione senza ancora aver scritto una sola riga di codice.
    Se li tratti bene, questi fanno tutto da soli le varie operazioni dal delete, insert, update. 

    Invece personalmente odio la bindingNavigator (sarà sicuramente per mio difetto perchè non riesco a tranne i vantaggi) e preferisco, se occorre, inserire manualmente i buttons per la gestione delle righe in insert, delete e update. Idem per i filtri e lo spostamento tra le righe del dataGrigView se occorre.

    Buon lavoro… ;-)

Devi accedere o registrarti per scrivere nel forum
21 risposte