7

Die Projekte in meiner Lösung sind wie folgt aufgebaut:Injecting DbContext in Repository-Klassenbibliothek

  • App.Data
  • App.Models
  • App.Web

In App. Daten, ich benutze Entity Framework, um mit einer Reihe von Repositories auf meine Daten zuzugreifen, um die Interaktion mit ihr zu abstrahieren. Aus offensichtlichen Gründen möchte ich, dass mein App.Web nur auf das App.Data-Projekt und nicht auf Entity Framework verweist.

I Constructor Injection bin mit meinem Controller einen Verweis auf ein Repository Behälter zu geben, die wie folgt aussieht:

public interface IDataRepository 
{ 
    IUserRepository User { get; set; } 
    IProductRepository Product { get; set; } 

    // ... 
} 

public class DataRepository : IDataRepository 
{ 
    private readonly AppContext _context; 

    public DataRepository(AppContext context) 
    { 
     _context = context; 
    } 

    // ... 
} 

DataRepository ein AppContext Objekt haben (die von Entity Framework erbt DbContext), dass alle das Kind Repositories verwenden, um auf die Datenbank zuzugreifen.

So kommen wir endlich zu meinem Problem: Wie verwende ich Constructor Injection auf DataRepository unter Berücksichtigung, es ist eine Code-Bibliothek und hat keinen Einstiegspunkt? Ich kann AppContext in App.Web nicht starten, weil ich dann Entity Framework von diesem Projekt verweisen muss.

Oder mache ich gerade etwas Dummes?

+0

keine Antwort auf Ihre Frage, sondern eine Menge von Repository-Schnittstellen zu definieren, versuchen, einen einzelnen 'IRepository ' Schnittstelle definiert, wie erklärt [hier] (http://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=92). Dies ermöglicht viel mehr Flexibilität. – Steven

+3

@Steven Danke für Ihren Kommentar. Aus diesem Grund bevorzuge ich spezifische Repositories: "Ein Repository ist ein Teil der zu modellierenden Domäne und diese Domäne ist nicht generisch. Nicht jede Entität kann gelöscht werden, nicht jede Entität kann hinzugefügt werden, nicht jede Entität hat ein Repository". http://stackoverflow.com/questions/1230571/advantage-of-creating-a-generic-repository-v-specific-repository-for-e-ach-obje – ajbeaven

Antwort

12

Sie können eine RepositoryConnection Klasse in App.Data definieren, die als Wrapper für den Kontext fungiert und die Notwendigkeit der Referenzierung von EF in App.Web beseitigt. Wenn Sie einen IoC-Container verwenden, können Sie die Lebensdauer der RepositoryConnection-Klasse steuern, um sicherzustellen, dass alle Instanzen von Repository denselben Kontext erhalten. Dies ist ein vereinfachtes Beispiel ...

public class RepositoryConnection 
{ 
    private readonly AppContext _context; 

    public RepositoryConnection() 
    { 
     _context = new AppContext(); 
    } 

    public AppContext AppContext { get { return _context; } } 
} 

public class DataRepository : IDataRepository 
{ 
    private readonly AppContext _context; 

    public DataRepository(RepositoryConnection connection) 
    { 
     _context = connection.AppContext; 
    } 

// ... 
} 
+0

Ah natürlich! Upvote diesen Mann! – ajbeaven

+0

Wenn alle Klassen den gleichen Kontext erhalten, wird der EF-Kontext nicht freigegeben, was schlecht, sehr schlecht ist. EF-Kontexte sind so konzipiert, dass Sie sie instanziieren, verwenden und entsorgen. –

+0

@BrunoBrant Sie sind absolut richtig - ein 'Context' sollte so kurzlebig wie möglich sein und diese Antwort unterstützt dies voll und ganz. Die Tatsache, dass wir eine "RepositoryConnection" haben, die als Brücke zwischen den Assemblies fungiert, ändert nichts. Die 'RepositoryConnection' und damit der 'Context' sind registriert ** Per Web Request **. Jede 'RepositoryConnection' (und daher auch 'Context') existiert im Rahmen einer einzelnen Web-Anfrage und bleibt daher für einige Sekunden am Leben. Sobald die Web-Anfrage beendet ist, werden die DI-verwalteten Klassen den Geltungsbereich verlassen und 'Disposed()' sein. – qujck