我目前正在使用EF 6设置.NET Core应用程序,并且在理解各种依赖项注册方法的适当用法方面遇到了一些问题。据我所知:
- Transient:需要时创建对象(即每次请求时都创建新实例)
- Singleton:应用程序启动时创建单个实例,并可用于所有后续请求
- Scoped:在请求期间可用
在我的情况下,我设置了一对基于CQRS模式的DbContext来处理数据库查询/命令,并将其注册为Scoped:
services.AddScoped((_) => new TestCommandContext(Configuration["Data:TestConnection:ConnectionString"]));
services.AddScoped((_) => new TestQueryContext(Configuration["Data:TestConnection:ConnectionString"]));
根据 ASP.NET Getting Started with ASP.NET 5 and Entity Framework 6 文档的说明:
为确保性能和 Entity Framework 的可靠操作,每个作用域应仅解析一次上下文。
接着我注册了相应的 UOW 类:
services.AddTransient<ITestCommandUnit, TestCommandUnit>();
services.AddTransient<ITestQueryUnit, TestQueryUnit>();
根据这篇文章,我在这里使用Transient。该文章建议:
使用Transient作用域注册的服务会在应用程序中需要时创建。这意味着依赖注入框架将在每次执行方法(其中创建依赖项)时创建(已注册服务)类的新实例。
基于这一理解,我也在将我的存储库和服务类注册为Scoped。
services.AddScoped<ITestCommandRepository, TestCommandRepository>();
services.AddScoped<ITestQueryRepository, TestQueryRepository>();
services.AddScoped<ITestCommandService, TestCommandService>();
services.AddScoped<ITestQueryService, TestQueryService>();
然后按需在我的控制器中调用我的相应服务层方法:
public class TestController : BaseController
{
private ITestQueryService testQueryService;
// Get new object of type TestQueryService via DI
public TestController(ITestQueryService testQueryService)
{
this.testQueryService = testQueryService;
}
[HttpGet]
public IActionResult Edit(int id)
{
if (id > 0)
{
EditViewModel viewModel = new EditViewModel();
viewModel.TestObject = testQueryService.GetById(id);
return View(viewModel);
}
else
{
return RedirectToAction("Error", new { errorMessage = "No object with the specified Id could be found." });
}
}
}
测试中,这个配置似乎在工作,将DbContext
设置为 Scoped 是有道理的 - 每次请求时创建一个新的上下文对象似乎是不必要/低效的。
然而,我不确定其他对象选择Transient
/Singleton
/Scoped
的最佳配置方案。能否有人帮助我了解此特定设计模式的最佳配置方案?
上述设置正在工作中,但我正在寻找更多了解为什么应该使用我选择的作用域(Scope
)。例如,我的 UOW 类应该使用 Transient 是最佳选择吗?在这种情况下,为什么Singleton
不是更好的选择?等等。