简体   繁体   中英

EFCore - How to run simple query on a loop?

I'm working on a project where users can queue up actions to happen in the future. Each future action is saved in the database. I'm trying to find a way to get all the actions that have already passed and act on them. Currently I'm doing this:

public class TaskingManager
{
    private static readonly System.Timers.Timer RefreshEventsLoop = new(1000);

    public void Initialize()
    {
        RefreshEventsLoop.Elapsed += RefreshEventsLoop_Elapsed;
        RefreshEventsLoop.AutoReset = false;
        RefreshEventsLoop.Start();
    }

    private void RefreshEventsLoop_Elapsed(object? sender, System.Timers.ElapsedEventArgs e)
    {
        RefreshEventsLoop.Enabled = false;
        ProcessEventsQueue();
        RefreshEventsLoop.Enabled = true;
    }

    private void ProcessEventsQueue()
    {
        var timeNow = DateTime.UtcNow;
        var context = new GalaxyDbContext(_dbOptions);
        var dbFunctions = new DatabaseFunctions(context);

        var eventsToProcess = context.FutureEvents
            .Where(futureEvent => futureEvent.TriggerTime <= timeNow)
            .ToList();

        if (eventsToProcess.Any())
        {
            context.FutureEvents.RemoveRange(eventsToProcess);
            context.SaveChanges();
            
            foreach (var pastEvent in eventsToProcess)
            {
                _messageMap[pastEvent.MessageType].Invoke(dbFunctions).Execute(pastEvent);
            }
        }
        else
        {
            dbFunctions.CreateFutureScienceTask();
        }
    }
}

This seems to work ok. But the problem is that after the app has been running for a while, I can see the LINQ part is taking up a huge amount of memory: 524MB used

And if I leave it running for a few days then it's up in the gigs.

I'm guessing running this query every second is wasteful on resources. But I don't know of a better way to do this. Is there a way to continuously check the database for something like this?

The first thing i can see is that you are not disposing the databasecontextt afer you used it. Read this for more info about entityframework context lifetime.

To properly dispose it use a using statement.

using (var context = new GalaxyDbContext(_dbOptions))
{
    //your code that uses the context
}

Or with new using syntax:

using (var context = new GalaxyDbContext(_dbOptions));
//your code that uses the context

Right know the problem could be that you create a context everytime you call the function and never dispose it and it still keeps references to the data etc..

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM