2012-08-02 4 views
5

MVC 4 프로젝트에서 NServiceBus (3.2.2), RavenDB (1.2.2017-Unstable) 및 Windsor (3.0.0.4001)를 사용하고 있습니다.NserviceBus에서 Windsor의 RavenDb 세션 관리

나는 3 가지 메시지를 처리하는 IHandleMessages 클래스가, 그 같은 속성을 IDocumentSession을 필요로하기 때문에 정의

public IDocumentSession DocumentSession { get; set; } 

나는 NServiceBus 'website

에서 RavenDbUnitOfWork 구현을 복사 한

나는 다음과 같이 내 윈저 컨테이너에 IDocumentStore, IDocumentSession 및 IManageUnitsOfWork 등록했습니다

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은 내 컨테이너를 사용하도록 구성되어 있습니다 : 나는 UnitOfWork에와 메시지 핸들러가 DocumentSession의 다른 인스턴스를받는 문제가 발생하고있어

Configure.With() 
     .CastleWindsorBuilder(container); 

. 즉, SaveChanges()가 다른 DocumentSession에서 호출되기 때문에 메시지 핸들러의 세션에 저장된 객체는 저장되지 않습니다.

과도한 라이프 스타일을 제거하면 RavenDb에서 객체를 업데이트 할 때 동시 처리/충돌이 발생하는 다른 종류의 문제가 발생합니다. 메시지 처리기가 캐시 된 버전의 업데이트를 보유하고있는 DocumentSession의 동일한 인스턴스를 계속 가져 오기 때문에 목적.

업데이트 : 제안 된 것과 같은

, 나는 다음과 같이 범위 라이프 스타일에, 윈저의 IDocumentSession의 등록을 변경 시도했다 :

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

이 예외를 컨테이너 시도의 원인 스코프를 찾을 수 없다는 MVC 컨트롤러를 해결하고 BeginScope()를 호출하는 것을 잊었는지 질문합니다.

+0

당신은 정의가 DocumentStoreHolder을 추가 할 수 있습니까? –

답변

4

메시지 당 범위가 필요하며 일시적 또는 단일 톤이 필요하지 않습니다.

+0

+1, LifecyleType.Scoped는 원하는 것입니다. https://github.com/NServiceBus/NServiceBus/blob/master/src/impl/ObjectBuilder/ObjectBuilder.CastleWindsor/WindsorObjectBuilder.cs#L175 –

+0

또한, 그 이유는 무엇입니까? RavenUnitOfWork는 DocumentSession 인스턴스 관리에 사용됩니다. – SaguiItay

+1

UoW는 .SaveChanges를 호출하기위한 것입니다. 창조와 처분은 용기에 의해 이루어진다. 그렇기 때문에 Scoped를 사용해야 메시지 당 새로운 세션을 만들 수 있습니다. –

0

mvc 컨트롤러에 IDocumentStore에 대한 직접 종속성이 있다고 가정합니다. 웹에서 요청할 때마다 container.BeginScope()를 호출해야합니다. 이를 액션 필터 속성 http://msdn.microsoft.com/en-us/library/system.web.mvc.actionfilterattribute.aspx으로 또는 컨트롤러 자체에서 AOP 애셋으로 http://cangencer.wordpress.com/2011/06/02/asp-net-mvc-3-aspect-oriented-programming-with-castle-interceptors/으로 지정할 수 있습니다.

0

동일한 컨테이너에서 IDocumentSession을 공유 할 때 asp.net mvc 웹 사이트에서 nservicebus를 사용하면 다른 라이프 스타일이 필요합니다.

ASP.NET MVC의 경우 PerWebRequest 라이프 스타일이 필요하고 NServiceBus의 경우 Scoped 라이프 스타일이 필요합니다.

내가 성있는 contrib 프로젝트에 하이브리드 라이프 스타일 코드를 사용했습니다 그렇게하려면 https://github.com/castleprojectcontrib/Castle.Windsor.Lifestyles/tree/master/Castle.Windsor.Lifestyles

하는 ASP.NET 환경에서 전화, 그것은 WebRequestScopeAccessor을 사용합니다. NServicebus에는 LifetimeScopeAccessor가 필요합니다.이 들어있는 contrib 프로젝트가 아니라 쉽게 추가 할 수 있습니다 :

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

그리고 당신의 등록 코드에서

당신이 같은 필요

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

을 그리고 여기에 내가 전환하기 전에 사용 코뿔소 서비스 버스의 구현입니다 nservicebus에 :

https://gist.github.com/4655544