2011-11-18 3 views
0

Ceci est ma première expérience avec EF, donc je fais probablement quelque chose de stupide. Tous les commentaires sur l'architecture sont les bienvenus.Référentiel personnalisé EF 4

J'ai donc la classe typique des utilisateurs. Les utilisateurs ont un nom d'utilisateur et une liste des rôles:

public class User 
{ 
    public string UserID{ get; set; } 
    public List<Role> Roles { get; set; } 
    public int Id { get; set; } 
    public User() 
    { 
     Roles = new List<Role>(); 
    } 
} 

Mes objets de domaine vivent dans leur propre bibliothèque de code ainsi que les interfaces pour leurs dépôts. Donc, dans ce cas, il y aurait un IUserRepository avec toutes les méthodes CRUD plus toutes les méthodes d'accès aux données spécialisées dont je pourrais avoir besoin. Ce que j'essaye de faire est d'implémenter ces interfaces de dépôt avec EF4 dans une autre bibliothèque de classes. Des problèmes avec cette conception jusqu'à présent?

Maintenant, dans le DB (serveur sql) j'ai les tables typiques: Utilisateurs, rôles, et un tableau de plusieurs-à-plusieurs mappage des utilisateurs aux rôles UsersRoles.

J'ai réussi à mettre en place la plupart des méthodes CRUD dans la bibliothèque EF. Voici à quoi ressemble Save

public void Save(Drc.Domain.Entities.Staff.User member) 
    { 
     using (var ctx = new DrcDataContext()) 
     { 
      var efUser = MapFromDomainObject(member); 
      if(member.Id < 1) 
      {      
       ctx.Users.AddObject(efUser);      
      } 
      else 
      {        
       ctx.Users.Attach(efUser); 
       ctx.ObjectStateManager.ChangeObjectState(efUser, EntityState.Modified); 
      }   
      ctx.SaveChanges(); 
      member.Id = efUser.UserId;     
     }    
    } 

Maintenant, je ne suis pas sûr que ce soit la bonne façon d'accomplir cela, mais cela fonctionne. Cependant, je rencontre des problèmes lors d'une suppression. Le problème est avec les tables liées

public void Delete(Drc.Domain.Entities.Staff.User member) 
    { 
     using (var ctx = new DrcDataContext()) 
     { 
      var efUser = MapFromDomainObject(member); ctx.Users.Attach(efUser); 
      while (efUser.Roles.Count > 0) 
      { 
       ctx.ObjectStateManager.ChangeObjectState(efUser.Roles.First(), EntityState.Deleted); 
      }       
      ctx.SaveChanges(); 
      ctx.ObjectStateManager.ChangeObjectState(efUser, EntityState.Deleted); 
      ctx.SaveChanges(); 
     } 
    } 

Si je ne supprime pas les rôles dans la boucle pendant que je reçois un conflit avec l'erreur de SUPPRIMER contrainte de référence. Si j'exécute le code ci-dessus, il supprime les lignes appropriées dans la table plusieurs-à-plusieurs, mais il supprime également les lignes dans la table Rôles. Je suis maintenant dans une impasse et je réfléchis à l'idée de l'ORM et à l'écriture de mes implémentations de référentiel dans un bon ADO.net fiable.

--Modifier Je suppose que ce n'est pas la bonne façon d'implémenter des dépôts avec EF. Est-il possible de se passer de votre domaine avec un tas de trucs EF?

+0

Je pense que votre problème est lié à la fonctionnalité Attacher/Détacher. Vous devriez vraiment récupérer l'objet de la base de données dans le contexte actuel, puis modifier leurs valeurs. Vous ne devriez pas vraiment avoir à supprimer les rôles, il suffit de supprimer l'efUser (assurez-vous que sa cascade marqué supprimer EF et DB) –

+0

J'ai pensé à cela, mais je ne voulais pas frapper la base de données pour obtenir l'utilisateur que je voulais supprimer. Je suppose que je suis en train de frapper de toute façon pour faire les suppressions donc je pourrais bien essayer ceci – cdaq

+0

Si j'utilise cette méthode, je vais devoir faire un get avant de sauvegarder aussi. Surly ce n'est pas la bonne façon d'y arriver. – cdaq

Répondre

0

Utilisez simplement l'approche standard et ne plaisante pas avec l'état de l'entité:

public void Delete(Drc.Domain.Entities.Staff.User member) 
{ 
    using (var ctx = new DrcDataContext()) 
    { 
     var efUser = MapFromDomainObject(member); 
     ctx.Users.Attach(efUser); 
     ctx.Users.DeleteObject(efUser); 
     ctx.SaveChanges(); 
    } 
} 

Il y a habituellement une suppression en cascade dans la base de données de la table User à la table de jointure (si vous ne l'avez pas le désactiver à la main). Donc, la suppression de l'utilisateur supprimera également les lignes correspondantes dans la table de jointure (mais pas les rôles bien sûr).

La définition de l'état d'une entité sur Deleted est différente de l'appel DeleteObject. Il ne définira que le parent à supprimer et laissera les enfants dans un état non supprimé dans le contexte, conduisant à l'exception de violation de contrainte. DeleteObject marquera également les enfants dans le contexte comme Deleted et donc éviter l'exception.

+0

Merci Slauma cela fonctionne. J'ai également dû activer les suppressions en cascade pour la table m: m. C'est désactivé par défaut. Je ne suis toujours pas sûr que ce soit la direction dans laquelle je veux aller. – cdaq