【问题标题】:Singleton in Asp.NET applicationAsp.NET 应用程序中的单例
【发布时间】:2014-12-18 16:15:24
【问题描述】:

在我的应用程序中,我为每个调用创建一个 dbcontext,并通过 Ninject 将其注入依赖项。

我一直在考虑创建一个单例类(ContextManager - BaseController 将为每个请求设置上下文)以使上下文在任何地方都可用,从而允许所有服务共享相同的上下文。这将进一步简化,例如,禁用代理创建等,因为上下文仅从一个地方进行管理。

但是,由于该对象是一个单例对象,因此每个请求都会覆盖上下文,这对我不起作用(我不希望多个请求共享一个上下文)。

最好的方法是什么(如何最好只在请求范围内使用单个上下文)?

【问题讨论】:

  • 这是 asp.net MVC 吗?
  • @Paddy 是的,但我使用的是 Web API 2。
  • 创建单例与使用 Ninject 有何不同/更好? Ninject 可以维护您的上下文的单例实例并传递它或为每个请求创建一个新实例等。
  • 另外,既然我们在这个话题上,Ninject 是所有 DI 容器中最慢的。从那以后,我停止使用 Ninject 并使用 SimpleInjector,这是最流行的一种。
  • @TheMuffinMan:这对您的平均响应时间提高了多少?

标签: c# asp.net entity-framework entity-framework-6


【解决方案1】:

您所描述的不是单例,而是请求范围的对象。 ASP.NET MVC 对依赖注入有很强的支持,你应该让你的 DI 绑定来确定上下文来自哪里,而不是自己实例化它。 Ninject 具有绑定语法来支持这一点。我认为是这样:

Bind<DataContext>().ToSelf().InRequestScope();

只要您始终使用良好的依赖注入模式,这应该会导致相同的 DataContext 实例被传递给您在同一请求中拥有的每个依赖项。

依靠依赖注入来构建上下文的优势在于,如果您想更改诸如禁用上下文更改跟踪等细节,您可以简单地更改您的 DI 绑定以使用自定义方法或工厂,其余的您的代码根本不需要更改。

【讨论】:

    【解决方案2】:

    单例在这里不是正确的方法,但这并不难实现,只需在控制器中实例化您的数据上下文并将其注入您的服务类,例如:

    public class SomeController {
    
         private DataContext _context;
         private SomeService _service;
    
         public SomeController() {
              _context = ...InstantiateContext();
              _service = new SomeService(_context);
         }   
    }
    

    如果您希望对其进行单元测试,这也使得将上下文注入控制器变得相对简单。您还可以通过将其编码到控制器类的 dispose 方法中来相对简单地处置您的上下文(如上所述,基控制器类可能很有用)。

    单例带有一些持久状态 - 这是单元测试的诅咒,最终会给你的代码带来困难。

    【讨论】:

      猜你喜欢
      • 2023-03-28
      • 1970-01-01
      • 2010-11-19
      • 2011-02-07
      • 2012-06-21
      • 1970-01-01
      • 2012-02-07
      • 2014-01-29
      • 1970-01-01
      相关资源
      最近更新 更多