7
votes

Détecter le changement d'état de la propriété de modèle, dans le contrôleur, en utilisant un cadre d'entité

J'ai un modèle plus ou moins d'aspect standard: xxx

si l'utilisateur modifie startDate ou projet durée , je dois Appelez une fonction pour mettre à jour une simulation. Afin de réaliser cela, je voudrais détecter la modification de l'état des champs startDate et Durée dans un contrôleur.

quelque chose comme ça: < / p> xxx

Voici un exemple de ce que la méthode du contrôleur ressemblerait à: xxx p> aucune idée, comment puis-je atteindre cette idée ?


0 commentaires

4 Réponses :


2
votes

Si vous voulez le faire sans interroger votre couche de persistance, je suppose ajouter les anciennes valeurs sous forme de champs de votre modèle, puis les garder dans la page car les champs cachés sont le moyen le plus simple de résoudre ce problème.

Ajoutez-le à l'arrivée actuelle. Courant-courant dans votre modèle: p> xxx pré>

puis ajoutez les champs masqués avec les anciennes valeurs à votre vue: p>

@Html.HiddenFor(model => model.CurrentStartDate )
@Html.HiddenFor(model => model.CurrentDuration )


3 commentaires

En fait, je préférerais faire toute la vérification dans le contrôleur si possible, conserve le nettoyeur de code. Pourriez-vous développer comment interroger votre calque de persistance , cela ressemble à ce que j'essaie d'atteindre.


Ensuite, vous devez récupérer le projet actuel à partir de votre DB et vérifier les anciennes valeurs et comparer aux valeurs que vous recevez du client.


J'ai déjà essayé que: je reçois l'exception suivante un objet avec la même clé existe déjà dans l'objetStatanager. L'objetStatanager ne peut pas suivre plusieurs objets avec la même clé.



10
votes

Je pense que vous pouvez comparer l'entité éditée avec l'original sur la lecture de la base de données.

quelque chose comme: xxx


7 commentaires

J'ai déjà essayé cela. Je reçois l'erreur suivante: `Un objet avec la même clé existe déjà dans l'objetStatanager. L'objetStatanager ne peut pas suivre plusieurs objets avec la même clé. Description: Une exception non gérée s'est produite lors de l'exécution de la demande Web actuelle. Veuillez consulter la trace de la pile pour plus d'informations sur l'erreur et où elle est originaire du code. Détails d'exception: System.InvalidoperationException: un objet avec la même clé existe déjà dans l'objetStatanager. L'objetStaTeManager ne peut pas suivre plusieurs objets avec la même clé.


Avec ou sans 'db.Entry (original) .state = entitéstate.modified;'?


OK, je suis corrigé, cela semble fonctionner, cependant, avoir à manuellement assigner original.value = projet.value; peut être un peu désordonné, cela peut être résolu en remplaçant db.Entry ( Original) .state = entitystate.Modifié; avec db.Entry (original) .CurrentValues.setvalues ​​(projet);


@ CHOPO87 S'il vous plaît, respectez les autres utilisateurs de ce site. Si vous trouvez une sorte d'erreur en réponse, s'il vous plaît éditer et corrigez-le . Ne laissez pas simplement les "mises à jour" dans les commentaires, car les commentaires sont des citoyens de deuxième classe ici et peuvent être facilement manqués. Essayez toujours de garder les réponses aussi précises que possible. Merci.


Pouvons-nous utiliser Mapeur automatique avec ViewModel et faciliter la tâche plutôt que d'écrire plusieurs || ?


@stom, bien sûr de pouvoir. Bien que vous puissiez obtenir la même chose en utilisant une propriété en lecture seule sur l'entité de projet qui encapsule ces conditions si je comprends bien ...


Je l'ai fait en utilisant bool modifié et || tel que vous avez mentionné, merci pour que cela soit clair en réalité, je reçois des détails d'adresse de livraison de l'utilisateur en utilisant un Formulaire généré avec Modèle , je veux vérifier si PostEdformValues! = Détails d'adresse de livraison existants dans la base de données, si la mise à jour de la mise à jour des détails de livraison modifiés dans la base de données, pouvez-nous utiliser Mapeur automatique ? Si oui, pouvez-vous montrer un exemple ou un lien de référence?



8
votes

Vous pouvez le résoudre en transportant de vieilles valeurs via ViewBag.

in Action: p> xxx pré>

Ajouter des éléments cachés à la vue p> xxx Pré>

Ajoutez ces paramètres à la méthode postale et vérifiez-les pour les modifications p>

[HttpPost]
public ActionResult Edit(DateTime OrigStartDate, int OrigDuration)
{
    if (ModelState.IsValid)
    {
        if (OrigStartDate != project.StartDate || OrigDuration != project.Duration)
            doSomething();

        db.Entry(project).State = EntityState.Modified;
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    ViewBag.FileTypeId = new SelectList(db.FileTypes, "Id", "TypeName", dbinfo.FileTypeId);
    return View(project);
}


1 commentaires

Je préfère cette solution, car il n'implique pas de tension supplémentaire à la base de données



2
votes

Utilisez .ASnoTracking (). FirstArdefault pour récupérer l'objet d'origine à titre de comparaison:

public ActionResult Edit(Project project)
{
    if (ModelState.IsValid)
    {
        Project original = db.AsNoTracking().FirstOrDefault( p => p.ID == project.ID);
        if (original.StartDate != project.StartDate || original.Duration != project.Duration)
            doSomething();

        db.Entry(project).State = EntityState.Modified;
        db.SaveChanges();
   }
   return View(project);
}


0 commentaires