使用Structureer为NServiceBus和MVC管理RavenDB IDocumentSession生命周期

 时-_尚微视点 发布于 2023-01-16 10:53

我在我们的解决方案中使用NServiceBus v4.3,MVC4,RavenDB 2.5和StructureMap 2.6.4.

我在StructureMap下遇到类似问题的问题,在这个问题的回答中我要求MVC控制器使用不同的生命周期,NServiceBus Handler在我的Web项目中使用RavenDB的IDocumentSession.

特别是在我的情况下,如果我使用HybridHttpOrThreadLocalScoped(如上面的答案建议Windsor)生命周期,会话没有被妥善处理,我很快就达到了30个事务限制错误.如果我使用HttpContext生命周期,则不会调用Web项目中的NSB事件处理程序.

在我的控制器中,会话被包含在通过MVC ActionFilter应用的工作单元中.我也使用处理程序中的UoW,因为我的注册表已连线以从UoW检索会话.代码是这样的:

RavenDbWebRegistry.cs

public sealed class RavenDbWebRegistry : Registry
{
    public RavenDbWebRegistry()
    {
        // register RavenDB document store
        ForSingletonOf().Use(() =>
        {
            var documentStore = new DocumentStore
            {
                ConnectionStringName = "RavenDB",
                Conventions =
                {
                    IdentityPartsSeparator = "-", 
                    JsonContractResolver = new PrivatePropertySetterResolver(),
                },

            };
            documentStore.Initialize();

            return documentStore;
        });


        For().HybridHttpOrThreadLocalScoped().Add(ctx =>
        {
            var uow = (IRavenDbUnitOfWork)ctx.GetInstance();
            return uow.DocumentSession;
        });

        For().HybridHttpOrThreadLocalScoped().Use();            

    }
}

Web项目处理程序示例:

public class SiteCreatedEventHandler : IHandleMessages
{
    public IBus Bus { get; set; }
    public IUnitOfWork Uow { get; set; }
    public IDocumentSession DocumentSession { get; set; }

    public void Handle(ISiteCreatedEvent message)
    {
        try
        {
            Debug.Print(@"{0}{1}", message, Environment.NewLine);

            Uow.Begin();
            var site = DocumentSession.Load(message.SiteId);
            Uow.Commit();

            //invoke Hub and push update to screen
            var context = GlobalHost.ConnectionManager.GetHubContext();

            //TODO make sure this SignalR function is correct
            context.Clients.All.displayNewSite(site, message.CommandId);
            context.Clients.All.refreshSiteList();            
        }
        catch (Exception ex)
        {                
            Uow.Rollback();
        }            
    }
}

ActionFilter的用法:

    [RavenDbUnitOfWork]
    public ViewResult CreateNew(int? id)
    {
        if (!id.HasValue || id.Value <= 0)
            return View(new SiteViewModel { Guid = Guid.NewGuid() });

        var targetSiteVm = MapSiteToSiteViewModel(SiteList(false)).FirstOrDefault(s => s.SiteId == id.Value);

        return View(targetSiteVm);
    }

WebRegistry(在我的MVC项目中设置NSB)

public sealed class WebRegistry : Registry
{
    public WebRegistry()
    {
        Scan(x =>
        {
            x.TheCallingAssembly();
            x.Assembly("IS.CommonLibrary.ApplicationServices");
            x.LookForRegistries();
        });

        IncludeRegistry();

        FillAllPropertiesOfType();
        FillAllPropertiesOfType();
        FillAllPropertiesOfType();
        FillAllPropertiesOfType>();
        FillAllPropertiesOfType>();
        FillAllPropertiesOfType();
        FillAllPropertiesOfType();
        FillAllPropertiesOfType();

        //NServiceBus
        ForSingletonOf().Use(
        NServiceBus.Configure.With()
            .StructureMapBuilder()
            .DefiningCommandsAs(t => t.Namespace != null && t.Namespace.EndsWith("Command"))
            .DefiningEventsAs(t => t.Namespace != null && t.Namespace.EndsWith("Event"))
            .DefiningMessagesAs(t => t.Namespace == "Messages")
            .RavenPersistence("RavenDB")
            .UseTransport()
            .DefineEndpointName("IS.Argus.Web")
            .PurgeOnStartup(true)
            .UnicastBus()
            .CreateBus()
            .Start(() => NServiceBus.Configure.Instance
            .ForInstallationOn()
            .Install())
        );


        //Web             
        For().Use(() => HttpContext.Current == null ? null : new HttpContextWrapper(HttpContext.Current));
        For().Use(GetModelBinders());
        For().Use();
        For().Use();
        For().Use();
        For().Use();
        For().Use();
        For().Use();
        For().Use();

        IncludeRegistry();
    }

我已经尝试使用我能想到的每种可能的组合配置我的注册表无济于事.

鉴于StructureMap混合生命周期不能像我期望的那样工作,我必须做些什么来实现正确的行为?

UoW对RavenDB是否必要/有益?我喜欢它(从我之前的NHibernate UoW ActionFilter中调整过它),因为它管理Controller Actions中会话的生命周期,但我对其他方法持开放态度.

理想情况下,我想要的是 - 在Web项目中 - 为控制器和处理程序分配完全不同的IDocumentSessions,但是无法以任何方式解决这个问题.

撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有