2010-01-15 15 views
13

Tengo una configuración de patrón de repositorio utilizando NHibernate. La clase base es el siguiente:Unidad de trabajo y el patrón de repositorio

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

    // ... 
} 

Como se puede ver, estoy permitiendo que la unidad de trabajo que se rellena a través de la constructora (usando StructureMap). Estoy instalando los objetos del repositorio en mis servicios web ASP.NET, así:

[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); 
    } 

    // ... 
} 

Como es posible que pueda deducir, mi problema es que por medio del diseño, ahora he perdido el control del ciclo de vida de la unidad de trabajo. Anteriormente, he hecho la unidad de trabajo un objeto sensible al contexto y el repositorio gustaría obtener una referencia a la misma a través de algo como:

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

    // ... 
} 

Este diseño anterior me permitió controlar el ciclo de vida de la unidad de trabajo en mi código creando la unidad de trabajo de un UnitOfWorkFactory dentro de una instrucción using. Estaba tratando de poner más trabajo en las manos del contenedor IoC, pero creo que realmente di un paso atrás. ¿Cuáles son sus pensamientos sobre cualquiera de las implementaciones?

Respuesta

3

Por lo general, es una buena idea dejar que su contenedor de IoC maneje tanto como sea posible. En la web, un patrón de unidad de trabajo generalmente se inicializa al inicio de la solicitud y se confirma al final (si hay alguna excepción). De esta forma, su repositorio tomará una ISession en el constructor en lugar de la unidad de trabajo. De esta forma, su repositorio no tendrá que lidiar con el compromiso o cualquier otra cosa y eso será manejado automáticamente por usted.

+0

¿Cómo se manejan las transacciones individuales en ese tipo de configuración? Digamos que necesito ejecutar dos juegos separados de código dentro de la misma sesión, y cada uno tiene su propia transacción. ¿Cómo recomendarías manejar eso? – Chris

+0

Las transacciones se manejan a través de la sesión. No necesita nada más que la referencia de sesión para usar una transacción. –

+3

La sesión de NHibernate es básicamente una unidad de trabajo en sí misma. La razón para esconderlo detrás de su propia interfaz de unidad de trabajo es básicamente para que pueda exponerlo de manera genérica al resto de la aplicación (fuera de su repositorio) y no depender de NHibernate. Y eso solo será inicializarlo al inicio de la solicitud y comprometerlo al final. –

Cuestiones relacionadas