在温莎管理RavenDb会议NServiceBus下(Managing RavenDb sessio

2019-07-30 17:44发布

我在MVC 4项目中使用NServiceBus(3.2.2),RavenDB(2017年2月1日 - 不稳定)和温莎(3.0.0.4001)。

我有一个处理3个不同的消息的IHandleMessages类,这点需要一个IDocumentSession,因此一个属性定义如:

public IDocumentSession DocumentSession { get; set; }

我已经复制从NServiceBus'的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配置为使用我的容器:

Configure.With()
         .CastleWindsorBuilder(container);

我现在遇到了的UnitOfWork和消息处理程序收到DocumentSession的不同实例的问题。 这意味着存储在消息处理程序中的会话对象不被保存,因为调用SaveChanges()被调用在不同DocumentSession。

卸下瞬态生活方式引起不同类型的问题,从RavenDb更新对象时,因为(可能)消息处理程序不断得到DocumentSession,其中包含更新的对象的缓存版本的同一个实例导致并发/冲突。

更新:

至于建议,我试图改变温莎IDocumentSession登记,到示波器的生活方式,就像这样:

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

这将导致异常时,容器尝试解析MVC控制器,称该范围没有被发现,并询问如果我忘了打电话给BeginScope()。

Answer 1:

你需要有每个消息,而不是短暂的或单的范围。



Answer 2:

我假设你的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/ 。



Answer 3:

问题是您分享在同一个容器中的IDocumentSession当一个asp.net mvc的网站使用nservicebus时需要不同的生活方式。

对于ASP.NET MVC你需要一个PerWebRequest生活方式和NServiceBus您需要的作用域的生活方式。

要做到这一点我已经使用在城堡的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



文章来源: Managing RavenDb session in Windsor under NServiceBus