2012-12-31 4 views
6

J'essaie de faire une mise à jour pour une table en utilisant EF 5.x en utilisant attach. cette table a d'autres champs qui sont requis mais c'est une ligne existante. donc j'essaye de mettre à jour sans aucun fetch. userid est la clé primaire de la table. J'essaie de mettre à jour le statut. mais il envoie un EntityValidationErrors indiquant qu'un mot de passe est requis, ce qui est un autre champ obligatoire mais pas une clé primaire. puisqu'il s'agit d'une mise à jour de la ligne existante, pourquoi devez-vous fournir les champs requis pour la mise à jour?Attacher pour Update Entity Framework

var webUser = new WebUser() { UserId = webUserId, OnlineStatus = (sbyte)status }; 
    using (var dbxupdate = new xEntities()) 
    { 
     try 
     { 
      dbxupdate.WebUsers.Attach(webUser); 
dbxupdate.Entry(webUser).State = EntityState.Modified; 
      dbxupdate.Entry(webUser).Property(x => x.OnlineStatus).IsModified = true; 
      dbxupdate.SaveChanges(); 
     } 
     catch (DbEntityValidationException dbEx) 
     { 
      foreach (var validationErrors in dbEx.EntityValidationErrors) 
      { 
       foreach (var validationError in validationErrors.ValidationErrors) 
       { 
        Trace.TraceInformation("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage); 
       } 
      } 
     } 
    } 
+0

Sur la première ligne, vous créez un nouveau 'webUser' et vous n'en extrayez pas un de la base de données. essayez de définir un point d'arrêt et vérifiez si le mot de passe 'webUser' n'est pas' null'. – Yoav

+0

Je ne voulais pas récupérer les données. puisque j'allais faire une mise à jour et j'ai déjà une clé primaire –

Répondre

1

Dans le cadre d'entité, vous ne pouvez pas mettre à jour un champ sans définir les valeurs appropriées pour les autres champs. il est donc préférable d'utiliser une procédure stockée pour votre travail. et l'autre façon est de récupérer l'enregistrement et ensuite mettre à jour le champ.

+1

Vous pouvez définir dbxupdate.Configuration.ValidateOnSaveEnabled = false pour désactiver la validation sur enregistrer comme dans http://stackoverflow.com/a/33121240/2353894 – nhkhanh

+0

La solution sale et la meilleure. Vous pourriez être confronté à BEAUCOUP de problèmes en essayant de mettre à jour une table existante en utilisant EF. – Jacob

2

L'entité est validée lors de la sauvegarde, qu'elle soit rattachée ou chargée à partir de la base de données. Si vous utilisez des attributs de validation ou une méthode de validation, l'entité doit valider la validation pour être enregistrée.

Si vous avez un attribut [Required] sur le champ de mot de passe, je pense que vous êtes assez bloqué. Vous devez probablement charger l'entité, puis mettre à jour les informations au lieu de simplement les joindre.

+0

non je n'ai pas cet attribut de données. son requis sur le niveau de DB mais pas sur EF, je suppose que ADO.net a tiré cet attribut de DB.Je ne vois pas cet attribut sur le code généré –

+0

il semble que je dois créer un SP pour le faire. –

+0

Si vous voulez mettre à jour seulement une partie de l'enregistrement sans d'abord charger l'entité entière, un SP est probablement un bon moyen oui. –

0

essayez ceci: remplacer la première ligne avec (ce lieu dans l'instruction using)
var wu = dbxupdate.webUsers.single(i=>i.id== webUserId);
wu.OnlineStatus = whatever;

code continue ... afin de mettre à jour une entité, vous devez obtenir une instance de celui-ci. Sinon, vous en créez un nouveau où les propriétés qui ne sont pas déclarées obtiennent une valeur null.

14

.Attach() est vraiment utile pour la mise à jour des entités dans un scénario détaché comme celui-ci:

User entity = null; 

using (var db = new DbContext()) 
{ 
    entity = (from p in db.Users 
       where p.id == 1 
       select p).FirstOrDefault(); 

    System.Diagnostics.Trace.WriteLine(entity.Name); //Outputs "Jane Doe" 
} 

entity.Name = "John Doe" //Modified while no longer connected to database 

using (var db = new DbContext()) 
{ 
    db.Users.Attach(entity); 
    db.Entry(entity).Property(a => a.Name).IsModified = true; 
    db.SaveChanges(); 

    System.Diagnostics.Trace.WriteLine(entity.Name); //Now outputs "John Doe" 
} 

Dans votre scénario, l'entité que vous créez est pas récupéré par sa clé et la base de données traite comme une entité entièrement nouvelle. Je suppose que votre mot de passe est un champ non nullable et donc EF renvoie une erreur lorsque vous essayez d'enregistrer vos modifications. Si vous n'aviez pas de telles erreurs, EF annulera automatiquement tous les champs que vous n'avez pas modifiés, puis sauvegardera l'entité (ce qui n'est pas non plus le résultat que vous recherchez).

Afin de faire les changements que vous cherchez, vous aurez probablement à faire quelque chose comme ce qui suit:

using (var db = new DbContext()) 
{ 
    db.Users.Single(a => a.id == 1).OnlineStatus = (sbyte)status; 
    db.SaveChanges 
} 

Et puis ajoutez tout autre code de gestion/validation erreur que vous voulez. Vous pouvez également stocker l'entité dans une variable pour apporter des modifications à plusieurs champs à la fois. EF doit automatiquement déterminer quelles valeurs ont été modifiées et générer uniquement le code SQL requis pour effectuer ces modifications. Ce qui signifie que si vous avez quelque chose comme:

foreach (var item in entityList) 
{ 
    var entity = db.Users.Single(a => a.id == item.id); 

    entity.Name = item.Name; 
    entity.Address = item.Address; 
} 

Quelqu'un me corriger si je me trompe, mais EF ne doit mettre à jour les entités/domaines qui sont réellement concernés par ce code. Si le nom ou l'adresse reste le même, EF ignorera ce champ pour cette entité lorsqu'il enregistre les modifications dans la base de données.