cela peut être une question triviale mais: Étant donné que l'infrastructure d'entité ADO.NET suit automatiquement les modifications (dans les entités générées) et conserve donc les valeurs d'origine, comment puis-je annuler les modifications apportées aux objets d'entité?
J'ai un formulaire qui permet à l'utilisateur d'éditer un ensemble d'entités "Client" dans une vue en grille.
Maintenant, j'ai deux boutons "Accepter" et "Revenir": si "Accepter" est cliqué, j'appelle Context.SaveChanges()
et les objets modifiés sont réécrits dans la base de données. Si vous cliquez sur "Revert", je voudrais que tous les objets obtiennent leurs valeurs de propriété d'origine. Quel serait le code pour cela?
Merci
la source
Context.Refresh()
est sûrement un contre-exemple à votre affirmation selon laquelle il n'y a pas d'opération de retour? L'utilisationRefresh()
semble être une meilleure approche (c'est-à-dire ciblée plus facilement sur des entités spécifiques) que d'éliminer le contexte et de perdre tous les changements suivis.Requête ChangeTracker de DbContext pour les éléments sales. Définissez l'état des éléments supprimés sur inchangé et les éléments ajoutés sur détachés. Pour les éléments modifiés, utilisez les valeurs d'origine et définissez les valeurs actuelles de l'entrée. Enfin, définissez l'état de l'entrée modifiée sur inchangé:
la source
State
de EntityState.Unchanged remplacera toutes les valeurs avecOriginal Values
ainsi il n'est pas nécessaire d'appeler laSetValues
méthode.Accession à MSDN :
Notez que le retour de la requête à la base de données présente certains inconvénients:
la source
Cela a fonctionné pour moi:
Où
item
est l'entité client à rétablir.la source
Un moyen facile sans suivre les modifications. Cela devrait être plus rapide que de regarder toutes les entités.
la source
Rollback
procédure ci-dessus , ce qui en fait un bien meilleur choix si l'on veut rétablir l'état de la base de données entière. Le retour en arrière pourrait choisir Tho.50ms+0*n= 50ms
. O (n) signifie que la performance est influencée par le nombre d'objets ... la performance est peut-être2ms+0.5ms*n
... donc en dessous de 96 objets, ce serait plus rapide mais le temps augmenterait linéairement avec la quantité de données.Cela a fonctionné pour moi. Cependant, vous devez recharger vos données à partir du contexte pour ramener les anciennes données. Source ici
la source
"Cela a fonctionné pour moi:
Où se
item
trouve l'entité cliente à rétablir. "J'ai fait des tests avec ObjectContext.Refresh dans SQL Azure, et le "RefreshMode.StoreWins" déclenche une requête sur la base de données pour chaque entité et provoque une fuite de performances. Basé sur la documentation Microsoft ():
ClientWins: les modifications de propriété apportées aux objets dans le contexte de l'objet ne sont pas remplacées par les valeurs de la source de données. Lors du prochain appel à SaveChanges, ces modifications sont envoyées à la source de données.
StoreWins: les modifications de propriété apportées aux objets dans le contexte de l'objet sont remplacées par les valeurs de la source de données.
ClientWins n'est pas non plus une bonne idée, car le déclenchement de .SaveChanges validera les modifications "ignorées" dans la source de données.
Je ne sais pas encore quel est le meilleur moyen, car l'élimination du contexte et la création d'un nouveau sont provoquées une exception avec le message: "Le fournisseur sous-jacent a échoué à l'ouverture" lorsque j'essaye d'exécuter une requête sur un nouveau contexte créé.
Cordialement,
Henrique Clausing
la source
Quant à moi, la meilleure méthode pour le faire est de définir
EntityState.Unchanged
chaque entité sur laquelle vous souhaitez annuler les modifications. Cela garantit que les modifications sont annulées sur FK et ont une syntaxe un peu plus claire.la source
J'ai trouvé que cela fonctionnait bien dans mon contexte:
Context.ObjectStateManager.ChangeObjectState(customer, EntityState.Unchanged);
la source
DbContext.SaveChanges()
, mais cela ne renverra pas les valeurs d'entité aux valeurs d'origine. Et si l'état de l'entité est modifié à partir d'un changement ultérieur, peut-être que toutes les modifications précédentes seront conservées lors de l'enregistrement?C'est un exemple de ce dont parle Mrnka. La méthode suivante avec les valeurs actuelles écrase les valeurs d' origine et d'une entité n'appelle la base de données. Pour ce faire, nous utilisons la propriété OriginalValues de DbEntityEntry et utilisons la réflexion pour définir des valeurs de manière générique. (Cela fonctionne à partir d'EntityFramework 5.0)
la source
Nous utilisons EF 4, avec le contexte d'objet hérité. Aucune des solutions ci-dessus n'a répondu directement à cela pour moi - même si elle a répondu à long terme en me poussant dans la bonne direction.
Nous ne pouvons pas simplement supprimer et reconstruire le contexte car certains des objets que nous avons en mémoire (putain de chargement paresseux !!) sont toujours attachés au contexte mais ont des enfants qui ne sont pas encore chargés. Dans ces cas, nous devons tout ramener à leurs valeurs d'origine sans marteler la base de données et sans abandonner la connexion existante.
Voici notre solution à ce même problème:
J'espère que cela aide les autres.
la source
Quelques bonnes idées ci-dessus, j'ai choisi d'implémenter ICloneable puis une méthode d'extension simple.
Trouvé ici: Comment cloner une liste générique en C #?
A utiliser comme:
De cette façon, j'ai pu cloner ma liste d'entités de produits, appliquer une réduction à chaque article et ne pas avoir à me soucier d'annuler les modifications apportées à l'entité d'origine. Pas besoin de parler avec le DBContext et de demander une actualisation ou de travailler avec le ChangeTracker. Vous pourriez dire que je n'utilise pas pleinement EF6, mais il s'agit d'une implémentation très simple et très simple qui évite un coup DB. Je ne peux pas dire si cela a un impact sur les performances.
la source