Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Managing RavenDb session in Windsor under NServiceBus

I'm using NServiceBus (3.2.2), RavenDB (1.2.2017-Unstable) and Windsor (3.0.0.4001) in an MVC 4 project.

I have a IHandleMessages class that handles 3 different messages, and that needs an IDocumentSession, and therefore defines a property such as:

public IDocumentSession DocumentSession { get; set; }

I've copied the RavenDbUnitOfWork implementation from NServiceBus' website

I've registered IDocumentStore, IDocumentSession and IManageUnitsOfWork in my Windsor container as follow:

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 is configured to use my container:

Configure.With()
         .CastleWindsorBuilder(container);

I'm encountering the problem that the UnitOfWork and the message handler receive different instances of the DocumentSession. This means that objects stored in the session in the message handler are not saved, since SaveChanges() is called on a different DocumentSession.

Removing the Transient lifestyle causes different kind of problems, that result in concurrency/conflicts when updating objects from RavenDb, since (probably) the message handler keeps getting the same instance of the DocumentSession, which holds a cached version of the updated object.

Update:

As suggested, I've tried changing the registration of the IDocumentSession in Windsor, to the Scope lifestyle, like this:

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

This causes exceptions when the container tries to resolve the MVC Controller, saying that the scope was not found, and asking if I forgot to call BeginScope().

like image 495
SaguiItay Avatar asked Oct 08 '22 01:10

SaguiItay


1 Answers

You need to have a scope of Per Message, not transient or singleton.

like image 66
Ayende Rahien Avatar answered Oct 13 '22 12:10

Ayende Rahien