C
C#3mo ago
Aleksandr

BackgroundService and dbcontext memory issue

I have a background service to update some objects. And for about 10 minutes of running the service everything is fine, the application uses about 1 GB of RAM, but after that the memory starts growing to 4+ GB, I checked the largest object and it is Microsoft.EntityFrameworkCore.Query.Internal.BufferedDataReader+BufferedDataRecord I checked this object, and there is by some objects, why? here is my code of dbcontext instance and screenshots of the problem, I tried to use the temporary database context, but it doesn’t work, if you run the code through the controller using a timer, then everything is ok, so I suspect dbcontext + ef core using var scope = _scope.CreateScope(); using var context = scope.ServiceProvider.GetRequiredService<WebApiContext>();
No description
No description
7 Replies
canton7
canton73mo ago
I think we need to see a bit more code than those 2 lines
Aleksandr
Aleksandr3mo ago
Is not so interesting, but of course here you are public class UpdateEntitiesBgService : BgService { public UpdateEntitiesBgService(IServiceScopeFactory scope) : base(scope) { } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { await ParseUrl(stoppingToken); } private async Task ParseUrl(CancellationToken stoppingToken) { await Task.Delay(TimeSpan.FromMinutes(3), stoppingToken); int skip = 0; const int take = 1; while (!stoppingToken.IsCancellationRequested) { try { var lCount = await Logic(skip, take, stoppingToken); skip = lCount == 0 ? 0 : skip += take; } catch (DbUpdateConcurrencyException ex) { ExceptionNotify(GetType().Name, ex.Message, ex.StackTrace); } catch (Exception ex) { ExceptionNotify(GetType().Name, ex.Message, ex.StackTrace); } await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken); } } private async Task<int> Logic(int skip, int take, CancellationToken stoppingToken) { using var scope = _scope.CreateScope(); using var context = scope.ServiceProvider.GetRequiredService<WebApiContext>(); var someService = scope.ServiceProvider.GetService<SomeService>(); var dateNow = DateTimeOffset.UtcNow; var ids = await context.Entities .Where(x => x.IsActive) .Skip(skip) .Take(take) .Select(x => x.Id) .ToListAsync(stoppingToken); await someService.UpdateEntities(ids, true); return ids.Count; } }
lycian
lycian3mo ago
$code
MODiX
MODiX3mo ago
To post C# code type the following: ```cs // code here ``` Get an example by typing $codegif in chat For longer snippets, use: https://paste.mod.gg/
Aleksandr
Aleksandr3mo ago
public class UpdateEntitiesBgService : BgService
{

public UpdateEntitiesBgService(IServiceScopeFactory scope) : base(scope) { }

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
await ParseUrl(stoppingToken);
}

private async Task ParseUrl(CancellationToken stoppingToken)
{
await Task.Delay(TimeSpan.FromMinutes(3), stoppingToken);

int skip = 0;
const int take = 1;

while (!stoppingToken.IsCancellationRequested)
{
try
{
var lCount = await Logic(skip, take, stoppingToken);

skip = lCount == 0 ? 0 : skip += take;
}
catch (DbUpdateConcurrencyException ex)
{
ExceptionNotify(GetType().Name, ex.Message, ex.StackTrace);
}
catch (Exception ex)
{
ExceptionNotify(GetType().Name, ex.Message, ex.StackTrace);
}
await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
}
}

private async Task<int> Logic(int skip, int take, CancellationToken stoppingToken)
{
using var scope = _scope.CreateScope();
using var context = scope.ServiceProvider.GetRequiredService<WebApiContext>();
var someService = scope.ServiceProvider.GetService<SomeService>();

var dateNow = DateTimeOffset.UtcNow;

var ids = await context.Entities
.Where(x => x.IsActive)
.Skip(skip)
.Take(take)
.Select(x => x.Id)
.ToListAsync(stoppingToken);

await someService.UpdateEntities(ids, true);

return ids.Count;
}
}
public class UpdateEntitiesBgService : BgService
{

public UpdateEntitiesBgService(IServiceScopeFactory scope) : base(scope) { }

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
await ParseUrl(stoppingToken);
}

private async Task ParseUrl(CancellationToken stoppingToken)
{
await Task.Delay(TimeSpan.FromMinutes(3), stoppingToken);

int skip = 0;
const int take = 1;

while (!stoppingToken.IsCancellationRequested)
{
try
{
var lCount = await Logic(skip, take, stoppingToken);

skip = lCount == 0 ? 0 : skip += take;
}
catch (DbUpdateConcurrencyException ex)
{
ExceptionNotify(GetType().Name, ex.Message, ex.StackTrace);
}
catch (Exception ex)
{
ExceptionNotify(GetType().Name, ex.Message, ex.StackTrace);
}
await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
}
}

private async Task<int> Logic(int skip, int take, CancellationToken stoppingToken)
{
using var scope = _scope.CreateScope();
using var context = scope.ServiceProvider.GetRequiredService<WebApiContext>();
var someService = scope.ServiceProvider.GetService<SomeService>();

var dateNow = DateTimeOffset.UtcNow;

var ids = await context.Entities
.Where(x => x.IsActive)
.Skip(skip)
.Take(take)
.Select(x => x.Id)
.ToListAsync(stoppingToken);

await someService.UpdateEntities(ids, true);

return ids.Count;
}
}
WEIRD FLEX
WEIRD FLEX3mo ago
are you omitting .AsNoTracking() intentionally?
Aleksandr
Aleksandr3mo ago
Yes, i use select, so AsNoTracking useless And in someService i get full entities by this ids, and there i dont use AsNoTracking cause i need to track changes