В настоящее время я работаю над настройкой приложения .NET Core с использованием EF 6, и у меня возникли проблемы с пониманием правильного использования различных методов регистрации зависимостей. Насколько я понимаю:
- Переходный: объект создается при необходимости (т.е. каждый раз, когда запрашивается новый экземпляр)
- Singleton: единственный экземпляр, созданный при запуске приложения, и доступный для всех следующих запросов
- Область: доступна на время запроса
В частности, в моей ситуации я настроил пару DbContexts (на основе шаблона CQRS) для обработки запросов/команд базы данных, которые я регистрирую как Scoped:
services.AddScoped((_) => new TestCommandContext(Configuration["Data:TestConnection:ConnectionString"]));
services.AddScoped((_) => new TestQueryContext(Configuration["Data:TestConnection:ConnectionString"]));
Это соответствует документации ASP.NET Начало работы с документами ASP.NET 5 и 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 (s) по мере того, как Scoped имеет смысл - кажется, не нужно/неэффективно создавать новый объект контекста каждый раз, когда он запрашивал.
Однако выбор между Transient/ Singleton/ Scoped для других объектов - это то место, где я потерялся. Может ли кто-нибудь помочь мне понять наилучшую конфигурацию для этой конкретной реализации шаблонов?
Вышеупомянутая настройка работает, но я ищу больше понимания того, почему я должен использовать области, которые я сделал. (т.е. Переходный лучший вариант для моего класса UOW? Почему это лучший выбор, чем Синглтон в этой ситуации?)