What is causing my Entity Framework Core dbContext to leak memory?

.net asp.net-core entity-framework entity-framework-core


This is involving Microsoft.EntityFrameworkCore.SqlServer, specifically version 2.1.14

I'm using EF within my service layer, and one of the APIs of this service is for bulk operations. All context dependent code uses constructor injection. The connection string does have MARS enabled. I register my database context like so:

services.AddDbContext<ServiceAvailabilityContext>(options => options.UseSqlServer(saConnection));

I have insured that all calling code is ran as a Scoped Task execution. I have a batch process that executes 50 simultaneous Task operations with a total of 500, and will try to run 500 regularly. However, I have noticed over time that the Heap Size memory consumption of this service just grows and grows. I have had this grow up to three gigs running the batch processor and service on my development machine, and also tried running the service Runtime build. Memory Snapshot Each service command or query is being ran within an IMediatR IRequestHandler and just to be sure that they were being invoked as Scoped I added pipeline behavior as such:

var response = await Task.Run(async () =>
            using (var scope = _serviceScopeFactory.CreateScope())
                return await next();

The call stack is basically Controller -> MediatR Request Handler(context constructor injected) -> Operation.

It seems like EF is just keeping all kinda of collections in memory and for some reason not releasing them even though the original context has passed out of scope, and all other references also passed out of scope. I'm not returning IQueryables and every time I retrieve data I'm doing an immediate .ToList() or .FirstorDefault() to finish the statement off. I never even return an entity object itself in a model but type cast them into a UI friendly object. I have also tried calling a method to hit a break point, and manually calling GC.Collect() which didn't release any memory!

My main question is just.... why? What am I missing?

2/27/2020 11:13:30 PM

Accepted Answer

It turns out that even though the DbContext was being used with DI scoped, the ChangeTracker behind the scenes keeps a hold of object HashSets. I had to change my retrieval statements to use AsNoTracking() when not modifying objects or detaching ones I did make changes to after calling SaveChanges() and that cleared up the memory problem.

3/4/2020 11:10:42 PM

Related Questions


Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow