2010-02-17 22 views
9

In meiner ASP.NET MVC-Anwendung habe ich ein Projekt, das die gesamte Geschäftslogik/Serviceschicht enthält. Dieses Projekt interagiert mit meiner Datenbank (Entity-Framework), die sich in einem separaten Projekt befindet.Anwendungsdienstschicht als statische Klassen

Ich wollte einfachen Zugriff auf die Service-Schicht, also habe ich statische Klassen in ihm erstellt, so dass sie leicht referenziert werden können. Zum Beispiel, wenn ich in meinem Controller bin und ich brauche ein neues Konto zu erstellen:

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

Die Service-Schicht dann nicht all erforderliche Logik, erstellt dann den Benutzer über das Repository in den 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);  
    } 

Da wollte ich nicht die folgenden überall in meiner Dienstschicht tun:

AccountRepository Accounts = new DatabaseLayer.AccountRepository(); 

ich eine Wrapper-Klasse für meine Repositorys stattdessen erstellt, so dass ich es nur einmal zu instanziiert zu verwenden alle anderen Repositories.

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+) 
    } 

Die in den statischen Klassen der Service-Schicht verwendet wurde.

Da alle meine Service-Layer-Klassen statisch sind und das Repos-Feld auch statisch ist, ist das offensichtliche Problem, das ich immer wieder vorfindet, wo das gleiche Objekt aus mehreren Datenkontexten abgerufen wird, seltsames Verhalten für Updates/Löschungen.

Ich verstehe, dass dies zu erwarten ist, wenn ich statische Mitglieder/Klassen verwenden, wie ich seit dem Lebenszyklus der Anwendung, aber gibt es eine Möglichkeit, die Service-Schicht als ServiceLayer.Accounts.Method() zu verwenden, ohne zu erstellen eine nicht statische Klasse, die überall dort instanziiert werden muss, wo sie verwendet wird, und die CRUD-Probleme aufgrund mehrerer Datenkontextinstanzen nicht auftreten?

+0

"tatsächlich sind einige der besten Hilfsmethoden statisch" Was ist Ihr Konzept von "best"? –

Antwort

15

Ihr Ansatz dazu ist wirklich kein empfohlen. Persönlich würde ich diese Art von Ansatz in meinem Team niemals zulassen. Die Nachteile:

  1. Wichtige Threadingprobleme, wie Sie erleben, die nicht einfach zu lösen
  2. Sie nicht das überhaupt sehr leicht testen.
  3. Unrealistische Abstraktion des Datenzugriffs,

Der wichtigste Grund für Instanzen von Endlagern zu schaffen, so dass Sie die Abhängigkeiten, wenn Sie benötigen injizieren können. Das bekannteste Argument hierfür ist Unit-Testing, so dass Sie die Abhängigkeiten spotten können, aber ich habe eine Reihe von Repositories mit Schnittstellenabhängigkeiten erstellt, die sich im Produktionscode ändern.

Sie sollten Ihre Repository-Instanziierung trotzdem als Teil Ihrer Basisserviceklassen einrichten.Es gibt keinen Grund, dass es "überall statisch OR Instanzanrufe sein muss". Innerhalb der Basisklassen sollte der Instanzinstanzierungscode begrenzt sein.

+0

Ich möchte auch hinzufügen, dass ich Probleme mit Eskalation zu MSDTC bei der Verwendung einer statischen Klasse zwischen dem Controller und dem Dienst – DevDave

10

Ich bin mir nicht sicher, warum Sie so gegen die Verwendung von Instanzen sind. Abgesehen von der Tatsache, dass der Code, den Sie jetzt haben, unnötig kompliziert ist, macht die Verwendung von statischen Typen auch den Einheitentest schwieriger. Der statische Typ ist wie ein Singleton, den Sie nicht nachahmen/ersetzen können. Es scheint mir, dass Ihre eigentliche Frage sein könnte: "Wie kann ich Instanzen meiner Serviceebene auf Lebenszeit verwalten?" In der Regel erfolgt dies mit einer Instanz pro Webanforderung. In einer ASP.NET MVC-Anwendung können Sie new up a DI container via a ControllerFactory, and handle all of this. [PDF]

1

Sie müssen den Umfang Ihrer Object in einer bewussten Art und Weise zu handhaben, wie ein von der Unit Of Work pattern

Apart tun, ich denke, Sie sollten alles tun, statisch überdenken, wie womp sagt man sehr hohe Kopplung zu erhalten, und macht es sehr schwierig zu testen, und Sie können eine Menge Hilfe bei der Verwaltung des Abhängigkeitsgraphen durch Verwendung eines IOC-Containers bekommen.

Ich kann das sagen, mir so etwas vorher :)

-3

Singletons tun verbrannt zu haben (und statische Klassen wie beschrieben) sind böse und sollte unter allen Umständen vor allem im Web Apps vermieden werden.

+0

Ich bin damit nicht einverstanden sind, Helper Methoden sind ideal, wenn statisch. Einige der besten Hilfsmethoden sind statisch für den Web-Einsatz. Anfrage, Server.MapPfad, Datei/Verzeichnis etc ... – Mike