17 messaggi dal 16 novembre 2010
Ciao a tutti,
una domanda su entity framework. E' possibile fare in modo che le navigation property con entity framework object context siano caricate con la megeroption overwritechanges in modo da caricare i dati puliti del database? Mi spiego. Ad esempio ho una relazione nel database uno a moti prodotti->ordini (un prodotto puo' essere inserito in più ordini). Con entityframework object context, l'entity "Prodotti" conterra' una navigation property che sara' definita nel Designer.cs in questo modo

public Ordini Ordini
        {
            get
            {
                return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference<Ordini>("Model.FK_Prodotti_Ordini", "Ordini").Value;
            }
            set
            {
                ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference<Ordini>("Model.FK_Prodotti_Ordini", "Ordini").Value = value;
            }
        }


Vorrei fare in modo che utilizzando questa navigation property mioProdotto.Ordini, gli ordini siano sempre caricati con l'overwritechanges (oppure preservechanges) in modo che i dati caricati siano quelli memorizzati nel database (noi lavoriamo in un ambiente concorrenziale).
Volevo sapere se c'era un modo, magari modificando il T4 template, senza dover passare per la query nel MVVM.

Spero di essermi spiegato e grazie a tutti
Modificato da paolo79 il 13 aprile 2015 16.38 -
11.884 messaggi dal 09 febbraio 2002
Contributi
Ciao Paolo,
vediamo se ho capito il problema: quando un utente modifica e risalva un ordine, è possibile che inavvertitamente sovrascriva le modifiche apportate poco prima da un altro utente.

Se è questo il caso, leggi qui, trovi un po' di informazioni sulla gestione della concorrenza con Entity Framework.
https://msdn.microsoft.com/en-us/library/bb738618.aspx

Per esempio, potresti abilitare la concorrenza ottimistica, in modo che i comandi SQL (UPDATE, in particolare) inviati dall'ObjectContext possano avere successo solo se la riga non è stata aggiornata nel mentre da qualcun altro.

Se fosse stata aggiornata, otterresti un'eccezione dal SaveChanges e a quel punto potresti gestirla e chiedere all'utente di decidere cosa fare (prendere per buoni i dati remoti, integrarli o sovrascriverli).

Questo è un esempio di una possibile strategia che viene suggerita nella documentazione.

If an optimistic concurrency violation has occurred, an OptimisticConcurrencyException is thrown. You can resolve an optimistic concurrency violation by catching it, calling the Refresh method with the StoreWins or ClientWins values, and then calling the SaveChanges method again.


Per ridurre la possibilità che l'eccezione si verifichi, potresti invocare un Refresh sull'ordine proattivamente, subito prima che l'utente visualizzi la maschera di modifica.

ciao,
Moreno

Enjoy learning and just keep making
17 messaggi dal 16 novembre 2010
Grazie BrightSoul, ma non è la gestione della Concurrency il problema. La questione è più semplice: voglio semplicemente caricare i dati della navigation property in modo che siano sempre coerenti con quelle che c'è nel database, senza dover per forza di cose passare dalla MVVM attraverso la mergeoption.overwritechages, ma diciamo "embeddare" l'overwritechanges direttamente nel code behind del model. Faccio un esempio molto banale:

ho una combobox con tutti i prodotti (master). Selezionato un item della combobox ho una listbox con tutti gli ordini del prodotto selezionato (detail). Carico gli items della listbox attraverso la navigation property "Ordini" del prodotto selezionato nella combobox (prodotto.Ordini).
Vorrei che ogni volta che seleziono un prodotto dalla combobox, gli ordini siano caricati utilizzando l'overwritechanges, ma per non scrivere troppo codice vorrei farlo direttamente nello xaml (wpf) utilizzando appunto la navigation property (comobobox.SelectedItem.Ordini) senza passare per l'mvvm.
11.884 messaggi dal 09 febbraio 2002
Contributi
Ciao Paolo,
ok, grazie per l'esempio, ora ho capito meglio il problema.

E ora mi torna anche il discorso del modificare il template T4. Effettivamente potresti andare a modificare il codice che genera il getter per la proprietà di navigazione. Una roba tipo:

((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference<<#=MultiSchemaEscape(navProperty.ToEndMember.GetEntityType(), code)#>>("<#=navProperty.RelationshipType.FullName#>", "<#=navProperty.ToEndMember.Name#>").Load(MergeOption.OverwriteChanges);
return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference<<#=MultiSchemaEscape(navProperty.ToEndMember.GetEntityType(), code)#>>("<#=navProperty.RelationshipType.FullName#>", "<#=navProperty.ToEndMember.Name#>").Value;

...però questo significherebbe influenzare tutte le proprietà di navigazione legate a collezioni, e questo potrebbe portarti a perdite di performance in altri punti dell'applicazione.

Se vuoi agire in maniera più controllata, anziché modificare il template T4, potresti crearti un nuovo file di codice .cs in cui ridefinisci la classe partial Prodotto e aggiungi una nuova proprietà, chiamata ad esempio "OrdiniAggiornati". Nel suo getter, invocherai .Load(MergeOption.OverwriteChanges) e restituirai il valore di Ordini, ora aggiornato.

ciao,
Moreno

Enjoy learning and just keep making
17 messaggi dal 16 novembre 2010
Ciao Moreno,
grazie mille, era quello che effettivamente avevo pensato di fare: modificare la partial class oppure utilizzare l'mvvm con il classico Master-Detail e facendo la query ogni volta che cambia l'item selezionato nel master. Tra l'altro ho notato questo spiacevole inconveniente modificando il code behind del model generato in modo che i dati caricati nella navigation property siano overwritechanges: funziona correttamente se nel database sono state modificate o aggiunte righe. Se invece vengono cancellate, comunque me le ritrovo nella navigation property. Ci sono alcuni aspetti di entity framework che ancora mi sfuggono, ma non importa...userò il tuo consiglio.
Grazie per l'aiuto che mi hai dato.

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.