J'ai exploré différentes méthodes de modification / mise à jour d'un enregistrement dans Entity Framework 5 dans un environnement ASP.NET MVC3, mais jusqu'à présent, aucune d'entre elles ne coche toutes les cases dont j'ai besoin. Je vais vous expliquer pourquoi.
J'ai trouvé trois méthodes auxquelles je mentionnerai les avantages et les inconvénients:
Méthode 1 - Charger l'enregistrement d'origine, mettre à jour chaque propriété
var original = db.Users.Find(updatedUser.UserId);
if (original != null)
{
original.BusinessEntityId = updatedUser.BusinessEntityId;
original.Email = updatedUser.Email;
original.EmployeeId = updatedUser.EmployeeId;
original.Forename = updatedUser.Forename;
original.Surname = updatedUser.Surname;
original.Telephone = updatedUser.Telephone;
original.Title = updatedUser.Title;
original.Fax = updatedUser.Fax;
original.ASPNetUserId = updatedUser.ASPNetUserId;
db.SaveChanges();
}
Avantages
- Peut spécifier quelles propriétés changent
- Les vues n'ont pas besoin de contenir toutes les propriétés
Les inconvénients
- 2 x requêtes sur la base de données pour charger l'original puis le mettre à jour
Méthode 2 - Charger l'enregistrement d'origine, définir les valeurs modifiées
var original = db.Users.Find(updatedUser.UserId);
if (original != null)
{
db.Entry(original).CurrentValues.SetValues(updatedUser);
db.SaveChanges();
}
Avantages
- Seules les propriétés modifiées sont envoyées à la base de données
Les inconvénients
- Les vues doivent contenir chaque propriété
- 2 x requêtes sur la base de données pour charger l'original puis le mettre à jour
Méthode 3 - Attachez l'enregistrement mis à jour et définissez l'état à EntityState.Modified
db.Users.Attach(updatedUser);
db.Entry(updatedUser).State = EntityState.Modified;
db.SaveChanges();
Avantages
- 1 x requête sur la base de données à mettre à jour
Les inconvénients
- Impossible de spécifier quelles propriétés changent
- Les vues doivent contenir chaque propriété
Question
Ma question à vous les gars; existe-t-il un moyen propre de réaliser cet ensemble d'objectifs?
- Peut spécifier quelles propriétés changent
- Les vues n'ont pas besoin de contenir toutes les propriétés (comme le mot de passe!)
- 1 x requête sur la base de données à mettre à jour
Je comprends que c'est une chose assez mineure à souligner, mais je manque peut-être une solution simple à cela. Sinon, la méthode prévaudra ;-)
la source
Réponses:
Tu recherches:
la source
J'aime vraiment la réponse acceptée. Je pense qu'il y a encore une autre façon d'aborder cela. Supposons que vous ayez une très courte liste de propriétés que vous ne voudriez jamais inclure dans une vue, donc lors de la mise à jour de l'entité, celles-ci seront omises. Disons que ces deux champs sont Mot de passe et SSN.
Cet exemple vous permet essentiellement de laisser votre logique métier seule après avoir ajouté un nouveau champ à votre table Utilisateurs et à votre vue.
la source
la source
J'ai ajouté une méthode de mise à jour supplémentaire à ma classe de base de référentiel qui est similaire à la méthode de mise à jour générée par Scaffolding. Au lieu de définir l'objet entier sur "modifié", il définit un ensemble de propriétés individuelles. (T est un paramètre générique de classe.)
Et puis appeler, par exemple:
J'aime un voyage dans la base de données. Il est probablement préférable de le faire avec des modèles de vue, afin d'éviter de répéter des ensembles de propriétés. Je ne l'ai pas encore fait car je ne sais pas comment éviter d'introduire les messages de validation sur mes validateurs de modèle de vue dans mon projet de domaine.
la source
la source
set
partie de l'instruction de mise à jour.Juste pour ajouter à la liste des options. Vous pouvez également récupérer l'objet dans la base de données et utiliser un outil de mappage automatique comme Auto Mapper pour mettre à jour les parties de l'enregistrement que vous souhaitez modifier.
la source
Selon votre cas d'utilisation, toutes les solutions ci-dessus s'appliquent. Voici comment je le fais habituellement cependant:
Pour le code côté serveur (par exemple un processus par lots), je charge généralement les entités et travaille avec des proxys dynamiques. Habituellement, dans les processus par lots, vous devez de toute façon charger les données au moment où le service s'exécute. J'essaie de charger les données par lots au lieu d'utiliser la méthode find pour gagner du temps. Selon le processus, j'utilise un contrôle de concurrence optimiste ou pessimiste (j'utilise toujours optimiste, sauf pour les scénarios d'exécution parallèle où j'ai besoin de verrouiller certains enregistrements avec des instructions SQL simples, cela est cependant rare). Selon le code et le scénario, l'impact peut être réduit à presque zéro.
Pour les scénarios côté client, vous avez quelques options
Utilisez des modèles de vue. Les modèles doivent avoir une propriété UpdateStatus (non modifié-inséré-mis à jour-supprimé). Il est de la responsabilité du client de définir la valeur correcte sur cette colonne en fonction des actions de l'utilisateur (insert-update-delete). Le serveur peut soit interroger la base de données pour les valeurs d'origine, soit le client doit envoyer les valeurs d'origine au serveur avec les lignes modifiées. Le serveur doit joindre les valeurs d'origine et utiliser la colonne UpdateStatus pour chaque ligne pour décider comment gérer les nouvelles valeurs. Dans ce scénario, j'utilise toujours une concurrence optimiste. Cela ne fera que les instructions d'insertion - mise à jour - suppression et pas de sélection, mais il faudra peut-être du code intelligent pour parcourir le graphique et mettre à jour les entités (cela dépend de votre scénario - application). Un mappeur peut aider mais ne gère pas la logique CRUD
Utilisez une bibliothèque comme breeze.js qui cache la majeure partie de cette complexité (comme décrit en 1) et essayez de l'adapter à votre cas d'utilisation.
J'espère que cela aide
la source