2012-08-02 11 views
5

Estoy usando NServiceBus (3.2.2), RavenDB (1.2.2017-Inestable) y Windsor (3.0.0.4001) en un proyecto de MVC 4.Administrar la sesión de RavenDb en Windsor bajo NServiceBus

tengo una clase que maneja IHandleMessages 3 mensajes diferentes, y que necesita un IDocumentSession, y por lo tanto define una propiedad, tales como:

public IDocumentSession DocumentSession { get; set; } 

He copiado la implementación de RavenDbUnitOfWork NServiceBus' website

me he registrado IDocumentStore, IDocumentSession y IManageUnitsOfWork en mi contenedor de Windsor de la siguiente manera:

container.Register(
      Component 
       .For<IManageUnitsOfWork>() 
       .ImplementedBy<RavenUnitOfWork>() 
       .LifestyleTransient() 
      ); 
container.Register(
      Component 
       .For<IDocumentStore>() 
       .UsingFactoryMethod(k => DocumentStoreHolder.DocumentStore) 
       .LifestyleSingleton(), 
      Component 
       .For<IDocumentSession>() 
       .UsingFactoryMethod(k => k.Resolve<IDocumentStore>().OpenSession()) 
       .LifestyleTransient() 
      ); 

NServiceBus está configurado para utilizar mi contenedor:

Configure.With() 
     .CastleWindsorBuilder(container); 

me encuentro con el problema de que el UnitOfWork y el controlador de mensajes reciben diferentes instancias de la DocumentSession. Esto significa que los objetos almacenados en la sesión en el controlador de mensajes no se guardan, ya que se llama a SaveChanges() en una DocumentSession diferente.

Eliminar el estilo de vida transitorio causa diferentes tipos de problemas, que resultan en concurrencia/conflictos al actualizar objetos de RavenDb, ya que (probablemente) el manejador de mensajes sigue recibiendo la misma instancia de DocumentSession, que contiene una versión almacenada en caché objeto.

Actualización:

Como se ha sugerido, He intentado cambiar el registro de la IDocumentSession en Windsor, al estilo de vida Ámbito de aplicación, así:

Component 
    .For<IDocumentSession>() 
    .UsingFactoryMethod(k => k.Resolve<IDocumentStore>().OpenSession()) 
    .LifestyleScope() 

Esto hace excepciones cuando los tries de contenedores para resolver el controlador MVC, diciendo que no se encontró el alcance, y preguntando si olvidé llamar a BeginScope().

+0

se puede añadir a la definición DocumentStoreHolder? –

Respuesta

4

Debe tener un alcance de Por mensaje, no transitorio o simple.

+0

+1, LifecyleType.Scoped es lo que quiere https://github.com/NServiceBus/NServiceBus/blob/master/src/impl/ObjectBuilder/ObjectBuilder.CastleWindsor/WindsorObjectBuilder.cs#L175 –

+0

Además, ¿no es por eso? RavenUnitOfWork usado para: administrar la instancia de DocumentSession? – SaguiItay

+1

La UoW está allí para llamar a .SaveChanges. La creación y la eliminación se realizan por el contenedor. Es por eso que necesita utilizar Scoped para obtener una nueva sesión por mensaje –

0

El problema es que necesita estilos de vida diferentes cuando usa nservicebus en un sitio web asp.net mvc cuando comparte IDocumentSession en el mismo contenedor.

Para ASP.NET MVC necesita un estilo de vida PerWebRequest y para NServiceBus necesita el estilo de vida Scoped.

Para hacer que he utilizado el código de estilo de vida híbrido en el proyecto castillo contrib: https://github.com/castleprojectcontrib/Castle.Windsor.Lifestyles/tree/master/Castle.Windsor.Lifestyles

Si llama desde un contexto ASP.NET, se utiliza el WebRequestScopeAccessor. Para NServicebus necesita el LifetimeScopeAccessor.Esto no está en el proyecto contrib, pero es fácil de añadir:

public class HybridPerWebRequestLifetimeScopeScopeAccessor : HybridPerWebRequestScopeAccessor 
{ 
    public HybridPerWebRequestLifetimeScopeScopeAccessor() 
     : base(new LifetimeScopeAccessor()) 
    { 
    } 
} 

Y en el código de registro que necesita algo como:

container.Register(Component.For<IDocumentSession>().LifestyleScoped<HybridPerWebRequestLifetimeScopeScopeAccessor>().UsingFactoryMethod(() => RavenDbManager.DocumentStore.OpenSession())); 

Y he aquí una aplicación para Rhino Service Bus i utilizado antes de cambiar a nservicebus:

https://gist.github.com/4655544

Cuestiones relacionadas