2012-08-02 9 views
5

Używam NServiceBus (3.2.2), RavenDB (1.2.2017-Unstable) i Windsor (3.0.0.4001) w projekcie MVC 4.Zarządzanie sesją RavenDb w Windsor pod NServiceBus

Mam klasy IHandleMessages który obsługuje 3 różne wiadomości, i że potrzebuje IDocumentSession, a więc określa właściwości takie jak:

public IDocumentSession DocumentSession { get; set; } 

Mam skopiowane wdrożenia RavenDbUnitOfWork z NServiceBus' website

mam zarejestrowany IDocumentStore, IDocumentSession i IManageUnitsOfWork w moim zbiorniku Windsor następująco:

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 jest skonfigurowany do korzystania z mojego kontenera:

Configure.With() 
     .CastleWindsorBuilder(container); 

ja napotykają problem, że UnitOfWork i obsługi wiadomości otrzymane różne instancje DocumentSession. Oznacza to, że obiekty przechowywane w sesji w module obsługi komunikatów nie są zapisywane, ponieważ funkcja SaveChanges() jest wywoływana w innej sesji DocumentSession.

Usunięcie stylu życia przejściowego powoduje różnego rodzaju problemy, które powodują współbieżność/konflikty podczas aktualizowania obiektów z RavenDb, ponieważ (prawdopodobnie) program obsługi wiadomości wciąż pobiera to samo wystąpienie sesji DocumentSession, która przechowuje buforowaną wersję zaktualizowanego obiekt.

Aktualizacja:

Jak sugeruje, próbowałem zmienić rejestrację IDocumentSession w Windsor, do życia Zakres, tak:

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

Powoduje to wyjątki, gdy próbuje kontenerów rozwiązać kontroler MVC, mówiąc, że zasięg nie został znaleziony i pytając, czy zapomniałem zadzwonić do BeginScope().

+0

można dodać definicję do DocumentStoreHolder? –

Odpowiedz

4

Musisz mieć zakres Per Message, a nie przejściowy lub singleton.

+0

+1, LifecyleType.Scoped jest tym, co chcesz https://github.com/NServiceBus/NServiceBus/blob/master/src/impl/ObjectBuilder/ObjectBuilder.CastleWindsor/WindsorObjectBuilder.cs#L175 –

+0

Czy to nie dlatego? używany RavenUnitOfWork - zarządzanie instancją DocumentSession? – SaguiItay

+1

The UoW jest tam, aby wywołać .SaveChanges. Tworzenie i usuwanie odbywa się przez pojemnik. Dlatego musisz używać Scoped, aby uzyskać nową sesję dla wiadomości –

0

Problem polega na tym, że podczas dzielenia obiektu IDocumentSession w tym samym kontenerze, potrzebny jest inny styl życia podczas korzystania z usługi nservicebus w witrynie asp.net mvc.

Dla ASP.NET MVC potrzebujesz stylu życia PerWebRequest, a dla NServiceBus potrzebujesz stylu Scoped.

Aby to zrobić Użyłem hybrydowy kod lifestyle w projekcie zamek contrib: https://github.com/castleprojectcontrib/Castle.Windsor.Lifestyles/tree/master/Castle.Windsor.Lifestyles

Dzwoniąc z kontekstu ASP.NET, używa WebRequestScopeAccessor. Dla NServicebus potrzebujesz LifetimeScopeAccessor.To nie jest w projekcie contrib, ale jest łatwy do dodania:

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

I w kodzie rejestracyjnym trzeba coś takiego:

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

A oto implementacja dla Rhino Service Bus użyłem przed włączeniem do nservicebus:

https://gist.github.com/4655544