【问题标题】:The request lifetime scope cannot be created because the HttpContext is not available无法创建请求生命周期范围,因为 HttpContext 不可用
【发布时间】:2012-06-14 20:11:28
【问题描述】:

很难尝试使用一些异步非 httprequest 设置 AutoFac。

我在 App_Start 上有以下内容

        var builder = new ContainerBuilder();
        builder.RegisterControllers(typeof(MvcApplication).Assembly);
        builder.RegisterType<sfEntities>().As<IUnitOfWork>().InstancePerHttpRequest();
        builder.RegisterGeneric(typeof(sfRepository<>)).As(typeof(IRepository<>)).InstancePerHttpRequest();
        builder.RegisterGeneric(typeof(BaseServices<>)).As(typeof(IBaseServices<>)).InstancePerHttpRequest();
        builder.RegisterType<EmailServices>().As<IEmailServices>().InstancePerHttpRequest();
        builder.RegisterType<UserServices>().As<IUserServices>().InstancePerHttpRequest();
        builder.RegisterType<ChatServices>().As<IChatServices>().InstancePerHttpRequest();
        builder.RegisterType<DefaultFormsAuthentication>();
        builder.RegisterType<WebSecurity>();
        builder.RegisterType<Chat>();
        IContainer container = builder.Build();
        DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

如果我更改为 InstancePerLifetimeScope(),我会遇到 UnitofWork.SaveChanges() 的问题。除了异步调用之外,这种方式的设置工作正常。

p.s.:UnitOfWork 在服务之间传递 EF DbContext 以确保使用相同的实例并正确处置。如果我更改为 InstancePerLifetimeScope,我在调用 .SaveChanges() 时会遇到身份冲突,可能是因为应该有多个 UnitOfWork 实例。

以下代码抛出以下异常:

Timer timer = new Timer(new TimerCallback(OnTimer), null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1));

    private static void OnTimer(object o)
    {
         using (var timerScope = AutofacDependencyResolver.Current.ApplicationContainer.BeginLifetimeScope())
         {
             var chatServices = timerScope.Resolve<IChatServices>();
             chatServices.MarkInactiveUsers();
         }
    }

从请求实例的范围中看不到带有与“httpRequest”匹配的标记的范围。这通常表明注册为 per-HTTP 请求的组件正在被 SingleInstance() 组件(或类似场景)请求。在 Web 集成下,始终从 DependencyResolver.Current 或 ILifetimeScopeProvider.RequestLifetime 请求依赖项,而不是从容器本身.

在 SignalR 上,以下代码引发以下异常:

SignalR.GlobalHost.DependencyResolver.Register(typeof(Chat), () => new Chat(DependencyResolver.Current.GetService<IUnitOfWork>(), DependencyResolver.Current.GetService<IChatServices>(), DependencyResolver.Current.GetService<IUserServices>()));

无法创建请求生命周期范围,因为 HttpContext 不可用

提前致谢!

【问题讨论】:

    标签: asp.net-mvc-3 autofac unit-of-work signalr


    【解决方案1】:

    很难尝试使用一些异步非 httprequest 设置 AutoFac。

    对于非 http 请求,或者更具体地说,对于非 ASP.NET 管道请求(如 WCF 或 ServiceStack),您绝对应该将所有 InstancePerHttpRequest() 代码更改为 InstancePerLifetimeScope()。你可以而且应该这样做,因为InstancePerLifetimeScope() will make it resolvable in both ASP.NET pipeline and non-ASP.NET pipeline contexts

    如果我更改为 InstancePerLifetimeScope(),我会遇到 UnitofWork.SaveChanges() 的问题。除了异步调用之外,这种方式的设置工作正常……如果我更改为 InstancePerLifetimeScope,我在调用 .SaveChanges() 时会遇到身份冲突,可能是因为应该有多个 UnitOfWork 实例。

    是的,UnitOfWork 的实例应该不止一个,但您可以通过一次注册来实现这一点,该注册的范围应为 InstancePerLifetimeScope()

    例子:

    builder.RegisterType<NhUnitOfWork>().As<IUnitOfWork>().InstancePerLifetimeScope();
    

    【讨论】:

    • 感谢@Jim,但很久以前我用 Ninject 替换了 AutoFac,我所有的问题都消失了。天哪,我记得我在这个问题上花了很多时间。
    • @JoaoLeme:啊。有趣的。也许我下次应该重新考虑 NInject。感谢您的提示。
    【解决方案2】:

    IChatServices 服务注册为InstancePerHttpRequest,因此只能在 http 请求生命周期范围内使用。您正在从无法“访问”当前请求的应用程序范围内解析,因此因您提到的错误而失败。所以是的,要让计时器工作,您必须在应用程序范围内注册服务。

    基本上,您可以拥有访问应用程序范围服务的请求范围服务,但反之则不行。

    问题是:UnitOfWork.SaveChanges 是做什么的,你遇到了什么“问题”?请详细说明。

    【讨论】:

    • UnitOfWork 在服务之间传递 EF DbContext 以确保使用相同的实例并正确处置。如果我更改为 InstancePerLifetimeScope,我会在调用 .SaveChanges() 时遇到身份冲突,可能是因为应该有多个 UnitOfWork 实例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-03
    • 1970-01-01
    • 1970-01-01
    • 2011-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多