我目前正在使用EF 6设置.NET Core应用程序,并且在理解各种依赖项注册方法的适当使用方面遇到了一些麻烦。据我了解:
特别是在我的情况下,我已经设置了一对DbContexts(基于CQRS模式)来处理我正在注册为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文档:
每个范围应解决一次上下文,以确保性能并确保实体框架的可靠运行
我正在注册相应的UOW类:
services.AddTransient<ITestCommandUnit, TestCommandUnit>();
services.AddTransient<ITestQueryUnit, TestQueryUnit>();
我在这里使用基于this文章的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在其他对象之间的选择是我迷失的地方。有人可以帮我理解这种特定模式实现的最佳配置吗?
前面提到的设置正在运行,但我正在寻找更多的理解为什么我应该使用我做的范围。 (即Transient是我的UOW课程的最佳选择?为什么在这种情况下它比Singleton更好?等等)
一般来说,我的经验法则是:
CreditLimit
将不会访问数据库。示例范围类? SqlConnection - 您不希望从单个请求(通常)打开与db的多个连接。也使用该连接进行服务(服务做一件事,所以不需要多个实例)。 Asp控制器。
单例示例?今天观看最多的文章。 Zip-code验证器(无依赖关系,纯方法)。
短暂的例子?想想如果该请求中的所有列表共享状态会发生什么。列表不是服务请求,而是您的代码,并且可以在单个请求期间用于不同目的。
请记住,如果单例具有瞬态或作用域依赖性,则在处理单例(应用程序循环)之前不会处置它。因此,作用域的东西可能依赖于单一的东西,但是单身人士不能依赖于作用域。
说到CQRS和DbContext - 在我的应用程序中,我有单个DbContext,由命令和查询共享。一切都是在每个生命周期范围内注册的(命令或查询在完成后没有保留状态,因此它们可以重复使用。将其设置为瞬态也会起作用)。另一个例子是为html元素生成唯一id的类。它被注册为作用域,并在每次查询新id时递增内部计数器。如果class是瞬态的,那么当从下一个类调用时它将失去其状态。
在您的情况下,您重新注入的服务不依赖于同一请求中的其他对象的状态。您使用该服务获取Db中的对象。瞬态或范围服务都可以工作。
如果在同一请求中您需要根据同一请求中的计算更改对象的状态,则需要使用从开头到结尾的同一请求中的对象(即:作用域)。