Почему я должен использовать AddScoped() для своих репозиториев или сервисов? Почему бы и нет AddSingleton()?
Я знаю о различиях между ними, но не понимаю, почему я не должен использовать экземпляры singleton, чтобы не создавать новые объекты для каждого запроса.
Можете ли вы объяснить это (желательно с примерами:))?
Пример. Если вы используете Entity Framework в качестве ORM, вы не можете зарегистрировать DbContext как Singleton, поскольку он не является потокобезопасным. Поэтому вы должны зарегистрировать его как переходный через AddDbContext.
Все дело в сохранении состояния, специфичного для запроса. Существует две модели хранения состояния, зависящего от запроса. В одна модель вы фиксируете данные времени выполнения в переменных объектов на вашем графике. Это требует использования Scoped образа жизни. Но есть другая модель, который хранит данные времени выполнения вне разрешенных объектов и сохраняет их как внешние данные. Это позволяет регистрировать объекты как синглтоны, потому что сами они не имеют никакого состояния.





Следующие три метода определяют время жизни сервисов,
AddTransient Временные сервисы жизненного цикла создаются каждый раз, когда они запрашиваются. Это время жизни лучше всего подходит для облегченных служб без сохранения состояния.
AddScoped Службы с ограниченным сроком службы создаются один раз для каждого запроса.
AddSingleton Службы времени жизни Singleton создаются при первом запросе (или при запуске ConfigureServices, если вы укажете там экземпляр), а затем каждый последующий запрос будет использовать один и тот же экземпляр.
Представьте, что у вас есть проект aspnet-core.
Если вы хотите создать объект только один раз во время выполнения программы и каждый раз использовать один и тот же объект, вы должны использовать addingleton.
Если вы хотите, чтобы объект снова был new() каждый раз, когда он получает запрос во время работы программы, вы должны использовать addscoped().
Если вы хотите, чтобы объект вызывал new() при каждом запросе и ответе, вы должны использовать AddTransient.
В типичном случае определение Scoped верно :) С технической точки зрения Scoped сервисы создаются не один раз для каждого запроса, а один раз для каждого сервиса. Просто так получается, что ASP.NET Core создает область для каждого запроса. Но вы также можете создать свои собственные области видимости в приложении, которые будут получать разные экземпляры, даже если это было во время одного и того же запроса.
@juunas, ты можешь отредактировать мой ответ?
Как вы сказали, вы знаете разницу, поэтому я не буду вдаваться в подробности.
Причина, по которой вам не нужен addSingleton для ваших репозиториев или служб, заключается в том, что обычно ваши репозитории и службы считаются «бизнес-логикой» и «логикой постоянства». И в вашей бизнес-логике у вас могут быть некоторые переменные уровня класса, которые устанавливаются. Эти свойства не будут различаться для каждого запроса, они будут общими для всех запросов. (думайте о них как о статических свойствах).
Пример:
Представьте, что у вас есть пользовательский сервис, который устанавливает имя пользователя, делающего запрос, как переменную уровня класса.
Логика синглтона:
Теперь представьте, что Боб делает запрос к API. Имя пользователя будет установлено на «Боб». А теперь представьте, в это же время Джон делает запрос к апи. Имя пользователя будет установлено на «Джон». Но поскольку пользовательский сервис является одноэлементным, и Джон, и Боб используют один и тот же экземпляр, а это означает, что имя пользователя Боба также будет установлено на «Джон».
Логика области действия:
Представьте точно такой же сценарий, как и выше, но на этот раз, когда Джон делает запрос, он не переопределяет имя пользователя bobs, потому что это разные экземпляры.
AddSingleton() — это одноэлементный режим, он уникален во всем контейнере, поэтому при запуске программы его экземпляр уникален. AddScoped() уникален в конкретном домене, и домены не влияют друг на друга.