4

I am using EF Core in my ASP.NET MVC Core (v1) application. And I notice while hosting my app on production for testing, the IIS Server normally recycles quite frequently due to reaching its memory limit.

I wanted to verify if the way I am using my dbContext in my application is valid and is not creating any memory leaks in the background. I have read some similar posts on SO where people recommend to dispose the context object after using it.

But I used it via dependency injection as follows.

Startup.cs class snippet:

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<Context>();
}

Context.cs class snippet:

    public class Context : IdentityDbContext<ApplicationUser> 
    {
        private IConfigurationRoot _config;
        private IHttpContextAccessor _HttpContextAccessor;

        public Context(IConfigurationRoot config, DbContextOptions options, IHttpContextAccessor HttpContextAccessor)
            : base(options)
        {
            _config = config;
            _HttpContextAccessor = HttpContextAccessor;
        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) 
        {
            base.OnConfiguring(optionsBuilder);

            optionsBuilder.UseSqlServer(_config["ConnectionStrings:ContextConnection"]);
        }
}

Does the services.AddDbContext<Context> inject a shared instance of the context, which results in a buildup of all entities queried over time and therefore is eating up memory?

EDIT: I also have a couple of the following singleton instances as follows:

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

services.AddSingleton<ILoggerService, LoggerService>();

services.AddSingleton<IEmailSender, EmailSender>();

Thanks!

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
JohnD
  • 41
  • 1
  • 3
  • 1
    `AddDbContext` adds a `Scoped` instance, so it's per request. Why are you injecting `IHttpContextAccessor` instead of just passing the configuration on `AddDbContext`? – Camilo Terevinto Feb 27 '18 at 23:24
  • Hi Camilo! I do that because I am also doing some background audit logging using a library called entity framework plus (http://entityframework-plus.net/) and therefore need some further information to perform some background audit logging. – JohnD Feb 27 '18 at 23:26
  • So since this a scoped instance, that means there is indeed no memory leaked being caused by my implementation of EF. Is there any way I could possible measure where the memory is being used up in my dev environment? Thanks! – JohnD Feb 27 '18 at 23:28
  • Not an easy one, no, you need to profile the application to see where it could go wrong. Not so long ago I answered a question of a memory problem when injecting `IConfiguration` as you seem to be doing (`_config = config;`) so check that as well – Camilo Terevinto Feb 27 '18 at 23:30
  • Camilo, I updated my post to also include some of the additional singleton definitions I have in my code. Is it recommended to change such items to scoped/transient? – JohnD Feb 27 '18 at 23:35
  • I was talking about [this post](https://stackoverflow.com/questions/47719346/asp-net-core-2-configuration-taking-up-a-lot-of-memory-how-do-i-get-config-info/47719638#47719638). `LoggerService` could be `Scoped`, depending on what it uses – Camilo Terevinto Feb 27 '18 at 23:42
  • Thanks Camilo. I had a read-through that. Just to put it out there my Logger server (concrete implementation) also injects into its constructor the dbContext and IHttpContextAccessor. Thats the reason I made it singleton. If I make it scoped, it would recreate those everytime correct? – JohnD Feb 27 '18 at 23:55
  • Not quite, `Scoped` means that an instance will be created for each HTTP Request, `Transient` is where a new instance is created each time a class needs it. A `Singleton` service can only require `Singleton` services since a HTTP request may or may not be alive when the service is requested, so that `Logger` should be `Scoped` – Camilo Terevinto Feb 28 '18 at 00:01

1 Answers1

2

In my case, In action filter and some middlewares, i used a IServiceProvider that created with services.BuildServiceProvider() like this:

public class DependencyManager{
    static class IServiceProvider ServiceProvider{ get;set;}
}
public class SomeMiddleware{
    public void SomeMethod(){
         var someServiceInstance = DependencyManager.ServiceProvider.GetService<SomeService>();
    }
}

Because of this, all scoped objects that created to inject this service are not linked to any request and will not disposed when request ends. I fixed this with using RequestServices under HttpContext:

public class SomeMiddleware{
    public void SomeMethod{
        var someServiceInstance = context.RequestServices.GetService<SomeService>()
    }
}
Cem Mutlu
  • 1,969
  • 1
  • 24
  • 24