2010-11-25 4 views
4

Résumé Problème:Linq sql: Relations pas correctement mis à jour

En utilisant la même DataContext à la fois insérer et mettre à jour un utilisateur avec un rapport à un certain nombre de rôles, les relations ne sont pas correctement mis à jour dans mes cours de LinqToSql (mais bien dans la base de données). En utilisant un DataContexts à insérer et un autre à mettre à jour fonctionne très bien.

Description détaillée:

J'ai une table utilisateur et une table de rôle dans ma base de données. Pour avoir une relation many-to-many entre eux, j'ai aussi une table UserRoleRelation (avec deux clés étrangères à User.ID et Role.ID).

J'ai un test où un utilisateur est créé et deux rôles (A et B) sont ajoutés à cet utilisateur. Ensuite, je supprime le rôle A et ajoute un nouveau rôle C et mettre à jour l'utilisateur.

Mais quand je puis sélectionnez l'utilisateur dans la base de données (par DataContext.Users.Where (p => p.ID.equals (user.id)). FirstOrDefault()), l'utilisateur n'a qu'un seul UserRoleRelation (au rôle A)! Mais tout va bien dans la base de données - les deux rôles A et C sont liés à l'utilisateur. J'utilise les services Web et donc le modèle de référentiel - pour chaque appel de service je crée un nouveau DataContext - cependant le même service peut manipuler le même objet (par exemple User, UserRoleRelation ou Role) plus d'une fois pour qu'ils soient déjà attaché au DataContext - donc quand j'attache des objets au DataContext, j'attrape des InvalidOperationExceptions potentielles (par exemple l'objet est déjà attaché) et je les ignore.

Dans mon test j'utilise le même DataContext pour insérer et mettre à jour l'utilisateur - cependant, si j'utilise deux DataContexts différents, alors cela fonctionne bien - l'utilisateur est correctement récupéré de la base de données!

Donc, pour une raison quelconque, la mise en cache dans le DataContext est foirée.

Voici ma méthode de UpdateUser:

private User UpdateUser(User user) 
{ 
    foreach (UserRoleRelation relation in user.UserRoleRelations) 
    { 
     if (relation.Role != null) 
     { 
      TryAttach(DataContext.Roles, relation.Role); // same as DataContext.Roles.Attach(relation.Role) 
     } 
    } 
    // attach the new user as modified 
    TryAttach(DataContext.Users, user, true); // same as DataContext.Users.Attach(user, true), but is that the correct way to do it? 

    // update the relations (figure out which are removed, added and unchanged) 
    IEnumerable<UserRoleRelation> oldRelations = DataContext.UserRoleRelations.Where(p => p.UserID.Equals(user.ID)).ToList(); 

    // mark for deletion (those elements that are in the old list, but not in the new) 
    IEnumerable<UserRoleRelation> deletionList = oldRelations.Except(user.UserRoleRelations, userRoleRelationComparer).ToList(); 
    DataContext.UserRoleRelations.DeleteAllOnSubmit(deletionList); 

    // mark for insert (those that are in the new list, but not in the old) 
    IEnumerable<UserRoleRelation> insertionList = user.UserRoleRelations.Except(oldRelations, userRoleRelationComparer).ToList(); 
    DataContext.UserRoleRelations.InsertAllOnSubmit(insertionList); 

    // attach the rest as unmodified (those that are in both lists) 
    IEnumerable<UserRoleRelation> unmodifiedList = oldRelations.Intersect(user.UserRoleRelations, userRoleRelationComparer).ToList(); 
    TryAttachAll(DataContext.UserRoleRelations, unmodifiedList); 

    DataContext.SubmitChanges(); 

    // return the updated user (in order to be sure that all relations are update, we fetch the user from the DB) 
    User updatedUser = GetUser(user.Email); // same as DataContext.Users.Where(p => p.Email.Equals(user.Email)).FirstOrDefault(); 
    return updatedUser; 
} 

Qu'est-ce que je fais mal? - Je suis à peu près sûr que lorsque j'utilise le même DataContext dans mon test, la "jointure de l'utilisateur au DataContext" lance une exception (il est déjà attaché), et c'est peut-être pour cela que je ne récupère pas les bonnes relations - mais LinqToSql devrait être capable de repérer le changement dans les relations ...

+0

Remarque: Dans le code, j'attends que la liste des rôles sur l'utilisateur donné figure déjà dans la base de données (c'est pourquoi ils sont simplement attachés au DataContext). – pcoltau

+0

il doit être en retard où je suis, je me sens comme si j'avais une réponse pour vous, mais c'est sur le bout de ma langue et je ne peux pas l'obtenir là-bas ... –

+0

Vous pourriez vouloir coller soit le DBML pour le trois tables ou les attributs pertinents sur les propriétés de classe générées. Essayez-le également sans beaucoup de vos propres emballages autour des méthodes, etc.pour s'assurer que ce n'est pas une question de cadrage étrange. – DamienG

Répondre

1

Je pense que le problème n'est pas sur la méthode Update mais ici "DataContext.Users.Where (p => p.ID.equals (user.id)) .FirstOrDefault() ", vous utilisez FirstorDefault() et linq retourne uniquement le premier des enregistrements. essayez de supprimer FirstOrDefault() et enregistrez les résultats sur un tableau ...

Questions connexes