0

I was looking through some code in an ASP.NET Core application and I noticed the repository services are added with AddScope, while in mine i am using addTransient. I have looked about the difference but i still do not understand how would this change my actual applicationn.

this is the code i am using and the services i use on pages for Get / Post actions.

 services.AddHttpContextAccessor(); services.AddSingleton<IFileProvider>(new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/files"))); services.AddTransient<IAuthorizationHandler, HasArranqueActivoHandler>(); services.AddTransient<IAuthorizationHandler, HasArranqueInactivoHandler>(); services.AddTransient<IAuthorizationHandler, IsParagemNotOnGoingHandler>(); services.AddTransient<IAuthorizationHandler, IsParagemOnGoingHandler>(); services.AddTransient<Services.Interfaces.IUserService, Services.UserService>(); #region AreaProduction services.AddTransient<Production.Interfaces.IComponenteService, Production.ComponenteService>(); services.AddTransient<Production.Interfaces.IReferenciaService, Production.ReferenciaService>(); services.AddTransient<Production.Interfaces.IProducaoRegistoService, Production.ProducaoRegistoService>(); services.AddTransient<Production.Interfaces.IParagemService, Production.ParagemService>(); services.AddTransient<Production.Interfaces.ICelulaService, Production.CelulaService>(); services.AddTransient<Production.Interfaces.IUapService, Production.UapService>(); services.AddTransient<Production.Interfaces.ICelulaTipoService, CelulaTipoService>(); services.AddTransient<Production.Interfaces.IMatrizService, MatrizService>(); services.AddTransient<Production.Interfaces.IOperadorService, Production.OperadorService>(); services.AddTransient<Production.Interfaces.IEtiquetaService, Production.EtiquetaService>(); services.AddTransient<Production.Interfaces.IPokayokeService, Production.PokayokeService>(); services.AddTransient<Production.Interfaces.IGeometriaService, Production.GeometriaService>(); services.AddTransient<Production.Interfaces.IEmpregadoService, Production.EmpregadoService>(); services.AddTransient<Production.Interfaces.IPecaService, Production.PecaService>(); services.AddTransient<Production.Interfaces.IDefeitoService, Production.DefeitoService>(); #endregion #region AreaRobotics services.AddTransient<Robotics.Interfaces.ITurnoService, Robotics.TurnoService>(); services.AddTransient<Robotics.Interfaces.ICelulaService, Robotics.CelulaService>(); services.AddTransient<Robotics.Interfaces.ICheckListService, Robotics.CheckListService>(); services.AddTransient<Robotics.Interfaces.IProducaoService, Robotics.ProducaoService>(); services.AddTransient<Robotics.Interfaces.IReferenciaService, Robotics.ReferenciaService>(); services.AddTransient<Robotics.Interfaces.IDefeitoService, Robotics.DefeitoService>(); services.AddTransient<Robotics.Interfaces.IDefeitoCodigoService, Robotics.DefeitoCodigoService>(); services.AddTransient<Robotics.Interfaces.IParagemService, Robotics.ParagemService>(); services.AddTransient<Robotics.Interfaces.IParagemCodigoService, Robotics.ParagemCodigoService>(); services.AddTransient<Robotics.Interfaces.IPecaService, Robotics.PecaService>(); services.AddTransient<Robotics.Interfaces.IUapService, Robotics.UapService>(); services.AddTransient<Robotics.Interfaces.IOperadorService, Robotics.OperadorService>(); #endregion #region AreaRobotics services.AddTransient<Areas.Robotics.Services.Interfaces.ITurnoService, Areas.Robotics.Services.TurnoService>(); services.AddTransient<Areas.Robotics.Services.Interfaces.ICelulaService, Areas.Robotics.Services.CelulaService>(); services.AddTransient<Areas.Robotics.Services.Interfaces.ICheckListService, Areas.Robotics.Services.CheckListService>(); services.AddTransient<Areas.Robotics.Services.Interfaces.IProducaoService, Areas.Robotics.Services.ProducaoService>(); services.AddTransient<Areas.Robotics.Services.Interfaces.IReferenciaService, Areas.Robotics.Services.ReferenciaService>(); services.AddTransient<Areas.Robotics.Services.Interfaces.IDefeitoService, Areas.Robotics.Services.DefeitoService>(); services.AddTransient<Areas.Robotics.Services.Interfaces.IDefeitoCodigoService, Areas.Robotics.Services.DefeitoCodigoService>(); services.AddTransient<Areas.Robotics.Services.Interfaces.IParagemService, Areas.Robotics.Services.ParagemService>(); services.AddTransient<Areas.Robotics.Services.Interfaces.IParagemCodigoService, Areas.Robotics.Services.ParagemCodigoService>(); services.AddTransient<Areas.Robotics.Services.Interfaces.IPecaService, Areas.Robotics.Services.PecaService>(); services.AddTransient<Areas.Robotics.Services.Interfaces.IUapService, Areas.Robotics.Services.UapService>(); services.AddTransient<Areas.Robotics.Services.Interfaces.IOperadorService, Areas.Robotics.Services.OperadorService>(); #endregion 

I would like to know what the impact of changing from AddTransient to AddScoped for my services in my application

Here is a simple Create page with many transient Services to populate select lists

 public class CreateModel : PageModel { private readonly IMatrizService _matrizService; private readonly IReferenciaService _referenciaService; private readonly IUapService _uapService; private readonly ICelulaTipoService _celulaTipoService; private readonly ICelulaService _celulaService; private readonly IToastNotification _toastNotification; private readonly ILogger<CreateModel> _logger; public CreateModel(IToastNotification toastNotification, ICelulaTipoService celulaTipoService, ICelulaService celulaService, IUapService uapService, IReferenciaService referenciaService, IMatrizService matrizService, ILogger<CreateModel> logger) { _matrizService = matrizService; _referenciaService = referenciaService; _uapService = uapService; _celulaTipoService = celulaTipoService; _celulaService = celulaService; _toastNotification = toastNotification; _logger = logger; } [BindProperty] public Matriz Matriz { get; set; } public void OnGet() { ViewData["CelulaId"] = new SelectList(_celulaService.GetAllFromCache(), "Id", "Nome"); ViewData["UAPId"] = new SelectList(_uapService.GetAllFromCache(), "Id", "Nome"); ViewData["ReferenciaId"] = new SelectList(_referenciaService.GetAllFromCache(), "Id", "Nome"); } public async Task<IActionResult> OnPostAsync() { if (!ModelState.IsValid) { ViewData["CelulaId"] = new SelectList(_celulaService.GetAllFromCache(), "Id", "Nome"); ViewData["UAPId"] = new SelectList(_uapService.GetAllFromCache(), "Id", "Nome"); ViewData["ReferenciaId"] = new SelectList(_referenciaService.GetAllFromCache(), "Id", "Nome"); _toastNotification.AddErrorToastMessage("Falha ao criar Matriz. Verifique os dados novamente."); return Page(); } _matrizService.Add(Matriz); try { await _matrizService.SaveChangesAsync(); } catch (DbUpdateException e) { //This either returns a error string, or null if it can’t handle that error _logger.LogError($@"Falha ao Adicionar Referência Area: Administration Page: Account/Robotics/Referencias/Create Error: {e.InnerException}"); _toastNotification.AddErrorToastMessage($"A Matriz com a Referência {Matriz.Referencia.Nome} já existe"); return Page(); } _toastNotification.AddSuccessToastMessage("Matriz criada com sucesso."); return RedirectToPage("./Index"); } } 

Most of my services are usually the same with crud methods

 public interface IUserService { IQueryable<User> GetAll(); User GetById(int id); void Add(User user); void Update(User user); int AddAndSave(User user); int SaveChanges(); int UpdateDateAndSave(User user); User GetByUsername(string username); } public class UserService : IUserService { private readonly DatabaseContext _context; public UserService(DatabaseContext context) { _context = context; } public void Add(User user) { _context.Users.Add(user); } public int AddAndSave(User user) { _context.Users.Add(user); return _context.SaveChanges(); } public IQueryable<User> GetAll() { return _context.Users.AsNoTracking(); } public User GetById(int id) { return _context.Users.Find(id); } public User GetByUsername(string username) { return _context.Users .Include(u => u.Colaborador) .Include(u => u.UserRoles) .ThenInclude(ur => ur.Role) .AsNoTracking() .FirstOrDefault(u => u.Username == username); } public int SaveChanges() { return _context.SaveChanges(); } public void Update(User user) { _context.Users.Update(user); } public int UpdateDateAndSave(User user) { user.DataSessao = DateTime.Now; _context.Users.Attach(user); _context.Entry(user).Property(u => u.DataSessao).IsModified = true; return _context.SaveChanges(); } } 
9
  • 1
    From the docs: Scoped lifetime services (AddScoped) are created once per client request (connection). Transient lifetime services (AddTransient) are created each time they're requested from the service container. What is your actual question? Commented Aug 12, 2019 at 14:27
  • 6
    Possible duplicate of AddTransient, AddScoped and AddSingleton Services Differences? Commented Aug 12, 2019 at 14:28
  • 1
    It's not really possible to assess how that change would impact your entire application without knowing the details of each dependency that is being registered/implemented. But knowing the difference between Scoped vs. Transient lifestyles (based on the previous comments), you should be able to look at your dependencies and determine how to configure their lifestyle appropriately. Maybe providing a specific example with just one of your services would better scope the question Commented Aug 12, 2019 at 14:35
  • 1
    Minor quibble, can't you add using Areas.Robotics.Services; to this file, it would make the code a little more readable :) Commented Aug 12, 2019 at 14:39
  • 1
    It's still not possible for us to help with this example. The key thing that you need to decide is what happens with the dependencies and how they interact with each other. For example, if two dependencies both take a third dependency, does that third item nee to be a distinct object or can it be shared. Commented Aug 12, 2019 at 14:44

1 Answer 1

3

how would this impact my application overall if i started using AddScoped for services

We would have to see a service (or, actually, all of them) to be sure.

But most likely it won't matter.

The thing to look out for is the state inside your services. Usually there is no state, and then Scoped or Transient won't matter.

So, do any of your service implementations have fields (other than injected services) ?

When they are currently registered as Transient then they are most likely stateless. And that makes the change to Scoped safe but still unnecessary.

Moving the other way (from Scoped to Transient) would require much more investigation.

Sign up to request clarification or add additional context in comments.

7 Comments

I updated my post with a service i use, most of my services are like this
Your DatabaseContext is probably the only service for which it matters. It should very much be Scoped.
that one is added using AddDbContext
And AddDbContext knows it has to be scoped. We should have better access to the docs for all these registration helpers.
No, all other services can and should be Transient (unless they have a special reason not to). I do not advice switching to Scoped at all. Also, don't fix anything that isn't broken.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.