2010-01-15 7 views
13

Ich habe ein Repository-Muster-Setup mit NHibernate. Die Basisklasse sieht wie folgt aus:Unit of work und das Repository-Muster

public interface IUnitOfWork : IDisposable 
{ 
    void Commit(); 
    void Rollback(); 
} 

// generic NHibernate implementation of IUnitOfWork here 

public class NHibernateRepositoryBase<T> : IRepository<T> 
{ 
    private NHibernateUnitOfWork _unitOfWork; 

    public NHibernateRepositoryBase(NHibernateUnitOfWork unitOfWork) 
    { 
     _unitOfWork = unitOfWork; 
    } 
    public T Get(object id) 
    { 
     return _unitOfWork.Session.Get<T>(id); 
    } 

    // ... 
} 

Wie Sie sehen, ich bin so dass die Einheit der Arbeit über den Konstruktor gefüllt werden (unter Verwendung von StructureMap). Ich bevölkern die Repository-Objekte auf meine ASP.NET Web-Services wie folgt:

[WebService(Namespace = "...")] 
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] 
public class ModuleService : System.Web.Services.WebService 
{ 
    public IUserAccountRepository UserAccountRepo { get; set; } 

    public ModuleService() 
    { 
     // tell IoC to inject properties 
     ObjectFactory.BuildUp(this); 
    } 

    // ... 
} 

Wie Sie in der Lage sein können, ableiten, mein Problem ist, dass, im Wege der Entwurf, den ich jetzt die Kontrolle über den gesamten Lebenszyklus verloren haben der Arbeitseinheit. Früher habe ich die Arbeitseinheit ein kontextsensitives Objekt und das Repository würde einen Verweis auf sie über so etwas wie erhalten:

public class NHibernateRepositoryBase<T> : IRepository<T> 
{ 
    public T Get(object id) 
    { 
     return NHibernateUnitOfWork.GetCurrent().Session.Get<T>(id); 
    } 

    // ... 
} 

Die bisherige Konstruktion erlaubte mir den Lebenszyklus der Einheit der Arbeit in meinem Code zu steuern durch Erstellen der Arbeitseinheit aus einer UnitOfWorkFactory innerhalb einer using-Anweisung. Ich habe versucht, mehr Arbeit in die Hände des IoC-Containers zu legen, aber ich glaube, ich habe tatsächlich einen Schritt zurück gemacht. Was halten Sie von beiden Implementierungen?

Antwort

3

Es ist normalerweise eine gute Sache, Ihren IoC-Container so gut wie möglich handhaben zu lassen. Im Web wird ein Arbeitseinheitsmuster in der Regel zu Beginn der Anfrage initialisiert und am Ende festgeschrieben (bei eventuellen Ausnahmen zurückgesetzt). Auf diese Weise nimmt Ihr Repository eine ISession im Konstruktor anstelle der Unit of Work. Auf diese Weise muss Ihr Repository nicht mit dem Commit oder irgendetwas fertig werden und das wird automatisch für Sie erledigt.

+0

Wie behandeln Sie einzelne Transaktionen in dieser Art von Setup obwohl? Angenommen, ich muss innerhalb derselben Sitzung zwei separate Code-Sätze ausführen, und jeder hat seine eigene Transaktion. Wie würdest du das behandeln? – Chris

+0

Die Transaktionen werden über die Sitzung abgewickelt. Sie benötigen nichts anderes als die Sitzungsreferenz, um eine Transaktion zu verwenden. –

+3

Die NHibernate-Sitzung ist im Grunde eine Einheit der Arbeit in sich selbst. Der Grund, es hinter der eigenen Unit of Work-Schnittstelle zu verstecken, ist im Grunde genommen so, dass Sie es generisch für den Rest der Anwendung (außerhalb Ihres Repositories) verfügbar machen können und nicht von NHibernate abhängig sind. Und das wird meistens nur sein, um es zu Beginn der Anfrage zu initialisieren und am Ende zu begehen. –