Kiyan
Kiyan

Reputation: 21

How to access database context outside of razor page?

I built a small web-app for college last semester and ran into an issue that I wasn't able to properly solve. The app is a price tracker that's using Selenium or curl to scrape products from webpages and track their price over time.
My issue is, how do I properly access the database context outside of the .cshtml.cs files? My current solution to this was to have a global variable that is assigned to the database context from the Main() class as such:

public static ProductContext globalContext; 
        public static void Main(string[] args)
        {
            var host = CreateHostBuilder(args).Build();
            var scope = host.Services.CreateScope();
            var services = scope.ServiceProvider; 
            globalContext = services.GetRequiredService<ProductContext>();

Then off in the scraping class I could save the found information as such: Program.globalContext.SaveChanges();

My global variable solution works for this, but it feels like a hacky solution at best. I had searched the internet as best I could, my professor wasn't able to offer a better solution either, but there has to be a way to do this right?

The full repository is here

Upvotes: 1

Views: 499

Answers (1)

Kiyan
Kiyan

Reputation: 21

I finally figured this out for myself, after doing research for another school project involving asp.net.

While reading the asp.net documentation I noticed the Background task with hosted services feature. From there I was able to piece together a plan using dependency injection to pass IServiceProvider into the IJob whenever Quartz is set to run the job. I think part of my original problem was the fact that I was trying to pass the database context to the IJob Execute method, which Quartz complained about. I also found this article about background tasks with Quartz to be quite helpful in developing my solution.
My IJob now looks like:

public class scrapeJob : IJob
    { 
        private IServiceProvider services {get; }
        public scrapeJob(IServiceProvider service)
        {
            services = service; 
        }
        async Task IJob.Execute(IJobExecutionContext context)
        { 
            Console.Out.WriteLine("Begin Scheduled Job...");
            using(var scope = services.CreateScope())
            {
                var dbContext = scope.ServiceProvider.GetRequiredService<ProductContext>(); 
                var scraper = new scrape(dbContext);
                await Task.Run(scraper.Scrape());  
            }
             
        }
    }

Link to Quartz.net

Upvotes: 1

Related Questions