2013-04-28 1 views
0

J'utilise entity framework pour conserver les données dans une application Wpf N-tier. Mon dbcontext est partagé entre tous les référentiels et n'est jamais éliminé. Quand je persiste, je marque un objet comme modifié et j'essaie d'enregistrer les changements. Si une erreur persiste pendant la persistance de l'objet, l'objet est toujours marqué comme modifié et si l'utilisateur abandonne l'opération en cours, il aura la même erreur lors de l'enregistrement d'un autre objet.Récupération après exception lors de l'utilisation d'un seul dbcontext

Je l'ai résolu en remplaçant SaveChanges dans mon dbcontext et si une erreur se produit j'accepte tous les changements (voir le code ci-dessous). Donc si une erreur accurs l'objet et tous les objets sont marqués inchangés même s'ils ne sont pas persévérés.

Cela ne semble pas normal ... Est-ce que quelqu'un est d'accord avec cette solution? Une autre solution consisterait à remplacer le dbcontext dans chaque méthode dans mes référentiels et à les éliminer immédiatement. Cela rendra mes dépôts plus compliqués et "noicy" et je perdrai aussi la possibilité de charger des données paresseuses ... Est-ce que quelqu'un a une solution différente pour moi?

//In my repositories 
    public void UpdateObject(Object object) 
    { 
     dbContext.Entry(object).State = EntityState.Modified; 
     dbContext.SaveChanges(); 
    } 

    //In my dbcontext class 
    private ObjectContext ObjectContext() 
    { 
     return (this as IObjectContextAdapter).ObjectContext; 
    } 

    public override int SaveChanges() 
    { 
     try 
     { 
      return base.SaveChanges(); 
     } 
     catch (Exception) 
     { 
      ObjectContext().AcceptAllChanges(); 
      throw; 
     } 
    } 

Répondre

0

Notre équipe utilise une approche similaire à ci-dessous:

Repository:

public class StudentRepository 
{ 
    private readonly MyEntities _context; 

    public StudentRepository(MyEntities context) 
    { 
    _context = context; 
    } 

    // Basic CRUD methods etc 
} 

Business Logic:

public AddStudent(Student student) 
{ 
    using(var context = new MyEntities()) 
    { 
     var studentrepo = new StudentRepository(context); 
     studentrepo.Add(student); 
     context.SaveChanges(); 
    } 
} 

Ceci est un exemple simplificatrice, mais devrait vous donner une idée. Pour réduire le code, nous utilisons également une classe de référentiel générique de base pour les méthodes CRUD. Si le projet sur lequel nous travaillons inclut un service Web, nous instancions le dbcontext dans le contrôleur API et surchargons la méthode Dispose pour nous en débarrasser.

+0

Je pense à votre solution :) J'ai réfléchi à votre solution et pour moi cela ne fonctionne pas bien. J'utilise TDD et injeciton de dépendance. Les repos sont envoyés via l'injection du constructeur dans ma logique métier.Avec votre solution, je devrais avoir une usine pour le dbcontext et une usine pour chaque référentiel. Cela donne l'impression de trop compliquer la logique métier et la logique métier avec des sujets qui ne les concernent pas ... – Jakob

+0

Dans la logique métier ci-dessus, le dbcontext et les référentiels peuvent être transmis via l'injection du constructeur. Comme je l'ai mentionné dans ma réponse, ce n'est qu'un exemple simplifié. Si vous effectuez des recherches sur Google à l'aide de mots clés tels que la durée de vie de la base de données dbcontext, vous constaterez que la plupart des utilisateurs recommandent d'avoir un contexte de courte durée. Dans ma propre expérience, nous avons trouvé un bug où quelqu'un avait oublié de se débarrasser d'un contexte et cela a causé une requête de 50 ms sur le webservice de prendre 3,2 minutes à exécuter. – failedprogramming

0

Avoir un tel contexte de vie n'est pas une bonne idée. Il deviendra grand et lent avec toutes les entités et les changements suivis, des problèmes liés à la concurrence peuvent survenir et les exceptions levées par votre contexte peuvent avoir un impact sur l'ensemble de votre application.

http://msdn.microsoft.com/en-us/data/jj729737

Une autre solution serait de nouveau la dbcontext dans chaque méthode dans mes repositores et d'en disposer tout de suite. Cela rendra plus compliqué mes dépôts et « noicy » et je vais aussi perdre la capacité aux données de charge paresseux

Dans un scénario déconnecté je voudrais créer et d'en disposer à chaque demande/unité de travail. Préoccupé par votre repos devenant compliqué? Alors n'utilisez pas cette couche supplémentaire d'abstraction. Les repos sont-ils vraiment nécessaires? Qu'est-ce que vous gagnez en utilisant directement le DbContext? En ce qui concerne le chargement paresseux, je pense que dans un scénario n-tier déconnecté, le chargement paresseux n'est pas vraiment approprié. Vous devriez probablement utiliser le chargement enthousiaste des données requises pour votre vue ou avoir des appels de méthode séparés pour obtenir les données connexes.

+0

Pense à vos vêtements :) :) Pour clearifier ma couche db est serpente et je n'expose rien du cadre d'entité. Je n'expose que des objets poco (code d'abord) pour que je puisse facilement changer ma couche db. J'utilise la couche db dans un client wpf et je prévois de l'utiliser dans une application Web et des services Web. Dans les derniers cas, il est facile de disposer du contexte après chaque requête. Je m'intéresse à la duplication du code de création et d'élimination du contexte et des performances. Pensez-vous toujours que votre solution est la meilleure pour moi? Dans le lien que vous avez envoyé, il est indiqué "un dbcontext par formulaire" qui pourrait fonctionner? – Jakob

Questions connexes