2010-02-17 5 views
9

Dans mon application ASP.NET MVC, j'ai un projet qui contient toute la logique métier/couche de service. Ce projet interagit avec ma base de données (Entity Framework) qui se trouve dans un projet distinct. Je voulais un accès facile à la couche de service, j'ai donc créé des classes statiques pour pouvoir facilement les référencer. Par exemple, si je suis dans mon contrôleur et je dois créer un nouveau compte:Couche de service d'application en tant que classes statiques

ServiceLayer.Accounts.CreateAccount(userName, passWord) //etc.. 

La couche de service ne puis toute la logique nécessaire, puis crée l'utilisateur via le référentiel dans le DatabaseLayer.

private static AllRepos _Repos; 
    private static AllRepos Repos { 
     get 
     { 
      if(_Repos == null) 
       _Repos = new AllRepos(); 

      return _Repos 
     } 
    } 

    public static void CreateAccount(string username, password) 
    { 
     string salt = GenerateSalt(); 
     Account newAccount = DatabaseLayer.Models.Account 
       { 
       Name = username, 
       Password = HashPassword(password, salt), 
       Salt = salt 
       }; 
     Repos.AddAccount(newAccount);  
    } 

Parce que je ne voulais pas faire ce qui suit partout dans ma couche de service:

AccountRepository Accounts = new DatabaseLayer.AccountRepository(); 

I au lieu de créer une classe wrapper pour mes référentiels pour que je ne l'instancier une fois à utiliser tous les autres dépôts.

public class AllRepos 
{ 

    private AccountRepository _Accounts; 

    public AccountRepository Accounts 
    { 
     get 
     { 
      if (_Accounts== null) 
       _Accounts= new AccountRepository(); 

      return _Accounts; 
     } 
    } 

    // the same is done for every other repository (currently have about 10+) 
    } 

Qui a été utilisé dans les classes statiques de la couche de service. Comme toutes les classes de ma couche de service sont statiques et que le champ Repos est également statique, le problème évident que je rencontre est celui où le même objet est récupéré à partir de plusieurs bases de données, provoquant des comportements étranges pour les mises à jour/suppressions. Je comprends que cela est normal si j'utilise des membres/classes statiques comme je l'ai fait depuis le cycle de vie de l'application, mais est-il possible d'utiliser la couche de service comme ServiceLayer.Accounts.Method() sans avoir à créer une classe non statique qui doit être instanciée partout où elle est utilisée et ne rencontre pas les problèmes CRUD dus à plusieurs instances datacontext?

+0

"En fait, certaines des meilleures méthodes d'aide sont statiques" Quel est votre concept de "meilleur"? –

Répondre

15

Votre approche n'est vraiment pas recommandée. Personnellement, je ne permettrais jamais ce type d'approche dans mon équipe. Les inconvénients:

  1. problèmes de filetage majeurs, comme vous rencontrez, qui ne sont pas simples à résoudre
  2. Vous ne pouvez pas tester très facilement du tout.
  3. abstraction Unrealistic de votre accès aux données

La principale raison de la création d'instances de dépôts est que vous pouvez injecter les dépendances si vous avez besoin. L'argument le plus connu est celui des tests unitaires, donc vous pouvez simuler les dépendances, mais j'ai construit un certain nombre de dépôts qui ont des dépendances d'interface qui changent dans le code de production.

Vous devriez tout simplement faire votre instanciation de référentiel dans le cadre de vos classes de service de base.Il n'y a aucune raison que cela doive être "statique OU appels d'instance partout". Il devrait y avoir un code d'instanciation d'instance limité dans les classes de base.

+0

Je voudrais également ajouter que j'ai rencontré des problèmes avec l'escalade MSDTC lors de l'utilisation d'une classe statique entre le contrôleur et le service – DevDave

10

Je ne suis pas sûr de savoir pourquoi vous êtes si dead-set contre l'utilisation des instances. Mis à part le fait que le code que vous avez maintenant est inutilement compliqué, l'utilisation de types statiques rend également plus difficile le test unitaire. Le type statique est comme un singleton que vous ne pouvez pas simuler/remplacer. Il me semble que votre vraie question pourrait être, "Comment puis-je gérer à vie des instances de ma couche de service?" Généralement, vous le faites en ayant une instance par requête Web. Dans une application ASP.NET MVC, vous pouvez new up a DI container via a ControllerFactory, and handle all of this. [PDF]

1

Vous devez gérer la portée de votre ObjectContext d'une manière délibérée, comme faire un Unit Of Work pattern

En dehors de cela, je ne pense que vous devriez revoir tout faire statique, comme womp dit que vous obtenez un couplage très élevé, et Cela rend le test très difficile, et vous pouvez obtenir beaucoup d'aide pour gérer le graphique de dépendance en utilisant un conteneur IOC.

je peux dire, après avoir brûlé moi-même faire ce genre de chose auparavant :)

-3

singletons (et les classes statiques comme décrit) sont mauvais et doivent être évités à tout prix en particulier dans les applications Web.

+0

je ne suis pas d'accord avec cela, les méthodes auxiliaires sont idéales lorsqu'elles sont statiques. En fait, certaines des meilleures méthodes d'aide sont statiques pour une utilisation sur le Web. Demande, Server.MapPath, Fichier/Répertoire etc ... – Mike

Questions connexes