Visualizzazione dei risultati da 1 a 7 su 7
  1. #1

    [Entity framework] Sincronizzare data context dopo eccezione

    Sto cercando un modo per lavorare in modo ultra-data-centric (tm) (r) su un database per mezzo di ADO.NET, non sono un FAN di questa tecnica, ma ho deciso di provare questa tecnologia per "velocizzare" lo sviluppo.

    Dopo avere chiamato savechanges sul datacontext, se savechanges solleva un eccezione, per esempio a causa di violazione di foreign key, il datacontext continua a contenere l'oggetto non valido, quindi l'utente continua a vederlo come se fosse stato realmente inserito in tutti i componenti GUI che si riferiscono per mezzo del binding al datacontext. Questo è un grosso problema: non posso dirgli chiudi e riapri il programma perchè non esiste un metodo "Ripristina Stato" in Entity Framework...

    Esiste una maniera di trovare e cancellare tutti gli oggetti in stato di errore nel datacontext?

    Questo è un esempio di codice che crea problemi:
    codice:
            public void Insert()
            {
                TQTZ_Contratti contratto = new TQTZ_Contratti();
                contratto.DescrizioneCorta = DescrizioneCorta;
                contratto.DescrizioneLunga = DescrizioneLunga;
                contratto.IDCliente = IDCLiente;
                contratto.IDDivisa = IDDivisa;
                            
                theDatabase.TQTZ_Contratti.AddObject(contratto);
    
                foreach (var orig in Origini)
                {             
                    contratto.Origini.Add(theDatabase.RGIS_NAZIONI.First(a=>a.ID_NAZIONE ==  orig.ID_NAZIONE));
                }
                foreach (var destinaz in Destinazioni)
                {
                    contratto.Destinazioni.Add(theDatabase.RGIS_NAZIONI.First(a=>a.ID_NAZIONE ==  destinaz.ID_NAZIONE));
                }
    
                theDatabase.SaveChanges();
                
            }
    durante savechanges potrebbe essere generata un eccezione, ma l'oggetto errato continua ad esistere nella cache. Qualche idea su come si potrebbe evitare questo? (La risposta controlla prima sul database che non ci siano conflitti non vale, devo risolvere la situazione dopo che l'eccezione è stata generata...)

    Ciao a tutti.

  2. #2
    Utente di HTML.it L'avatar di cassano
    Registrato dal
    Aug 2004
    Messaggi
    3,002
    MSDN

    Esempi
    --------------------------------------------------------------------------------

    Questo esempio è basato sul modello descritto in Adventure Works Sales Model. In questo esempio si tenta di salvare modifiche che possono provocare un conflitto di concorrenza. Viene quindi illustrato come risolvere il conflitto di concorrenza aggiornando il contesto dell'oggetto prima di salvare nuovamente le modifiche.


    codice:
    Using context As New AdventureWorksEntities()
        Try
            ' Perform an operation with a high-level of concurrency. 
            ' Change the status of all orders without an approval code. 
            Dim orders As ObjectQuery(Of SalesOrderHeader) = context.SalesOrderHeaders.Where("it.CreditCardApprovalCode IS NULL").Top("100")
    
            For Each order As SalesOrderHeader In orders
                ' Reset the order status to 4 = Rejected. 
                order.Status = 4
            Next
            Try
                ' Try to save changes, which may cause a conflict. 
                Dim num As Integer = context.SaveChanges()
                Console.WriteLine("No conflicts. " & num.ToString() & " updates saved.")
            Catch generatedExceptionName As OptimisticConcurrencyException
                ' Resolve the concurrency conflict by refreshing the 
                ' object context before re-saving changes. 
                context.Refresh(RefreshMode.ClientWins, orders)
    
                ' Save changes. 
                context.SaveChanges()
                Console.WriteLine("OptimisticConcurrencyException handled and changes saved")
            End Try
    
            For Each order As SalesOrderHeader In orders
                Console.WriteLine(("Order ID: " & order.SalesOrderID.ToString() & " Order status: ") + order.Status.ToString())
            Next
        Catch ex As UpdateException
            Console.WriteLine(ex.ToString())
        End Try
    End Using

  3. #3
    che dire, se funziona è veramente bello ed elegante, stavo già ravanando nell' ObjectStateManager per riimpostare a mano lo stato dei singoli oggetti.

    Grazie ora provo.

  4. #4
    Utente di HTML.it L'avatar di cassano
    Registrato dal
    Aug 2004
    Messaggi
    3,002
    Funziona che si .

  5. #5
    Ciao, non funziona, infatti il mio caso è differente rispetto all'eccezione generata a causa di un inserimento NonOttimistico nel database.

    Io parlo di un eccezione qualunque causata da un fallimento nella chiamata di SaveChanges.

    Non voglio generare per questo progetto alcuna verifica lato client o middle tier, voglio lavorare in modo data-centric puro, il client deve essere perfettamente ignorante, pertanto può tentare di inserire o modificare record che violano i vincoli del database, se ci riesce bene, altrimenti deve dire all'utente "Spiacente non è possibile".

    Se chiamo SaveChanges dopo avere tentato di inserire un record errato in una tabella, che non possa essere accettato perchè duplicherebbe una primary key.. giustamente SaveChanges fallisce e l'eccezione sollevata fornisce un messaggio più che sufficiente per l'utente.

    Ora io voglio soltanto che il datacontext locale ritorni allo stato precedente all'inserimento del record errato.

    Ho cercato lungamente in rete, e vedo che diverse persone si lamentano della mancanza di un metodi tipo DataContext.DiscardAllChanges() la cosa migliore sarebbe una cosa del tipo

    codice:
    CheckPoint pippo = DataContext.CreateCheckPoint();
    DataContext.Entity.AddObject(Sbagliato);
    try{
       DataContext.SaveChanges();
    }
    catch(Exception e)
    {
        DataContext.DiscardChanges(pippo);
        throw e;
    }
    Questo consentirebbe di creare un client completamente ignorante senza richiedere un ricaricamento dei dati dalla sorgente nel datacontext.

    Ad ogni modo per il tipo di applicazione che sto facendo diventa esageratamente complesso andare a smanettare nel ObjectStateManager per implementare manualmente una situazione come quella di cui sopra, pertanto mi va piu che bene ricaricare i dati nel context utilizzando una query con MergeOption = OverwriteChanges... è un ripiego ma per il tipo di client ignorante che intendo fare ce n'è d'avanzo... (parlo di applicazione desktop non applicazione web)

    codice:
    private Context theContext = new Context();
    private Reload()
    {
        var Query = theContext.Entity.Where("parametri");
        ...
        this.DataContext = Query.Execute(MergeOption.OverwriteChanges);            
    }
    
    private void TentativoInsert()
    {
         FormNewRecord r = new FormNewRecord();
         r.owner=this;
         r.ShowDialog();
         theContext.Entity.Add(r.NewRecord);
         try{
              theContext.SaveChanges();
         }
         catch(Exception e)
         {
             Reload();
             MessageBox.Show(e.Message);
         }
    }
    Ciao e grazie.

  6. #6
    Utente di HTML.it L'avatar di cassano
    Registrato dal
    Aug 2004
    Messaggi
    3,002
    Bè scusa , questo dovrebbe fare al caso tuo :

    codice:
    StoreWins  Le modifiche delle proprietà apportate agli oggetti nel contesto dell'oggetto vengono sostituite con i valori presenti nell'origine dati.

  7. #7
    E' equivalente a ricaricare i dati dallo store rieseguendo la query dal database.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.