Search code examples
c#entity-frameworkazuredbcontextwebjob

Configure a dbContext from a webjob


I have a website that takes input from emails that go out to users (an email is sent to everyone, they click a link which calls a controller action). I want to use a webjob to send the emails out, but I need to cycle through all the users in the database to grab the email addresses.

I set up the website and everything is working great. I have the DbContext inheriting from IdentityDbContext here:

public class MooodDbContext : IdentityDbContext<ApplicationUser>
    {
        public MooodDbContext(DbContextOptions options) : base(options)
        {

        }

        public DbSet<Response> Response { get; set; }

        public DbSet<Cow> Cow { get; set; }

        public DbSet<Herd> Herd { get; set; }
    } 

The ConfigureServices is run when I launch the webapp

public void ConfigureServices(IServiceCollection services)
        {
            // Add framework services.
            services.AddDbContext<MooodDbContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("MooodConnection")));

            services.AddIdentity<ApplicationUser, IdentityRole>()
                .AddEntityFrameworkStores<MooodDbContext>()
                .AddDefaultTokenProviders();

            services.AddMvc(options => options.Filters.Add(typeof(UnauthorizedExceptionFilterAttribute)));

            services.AddScoped<IDbInitializer, DbInitializer>();

            // Add application services.
            services.AddTransient<IEmailSender, AuthMessageSender>();
            services.AddTransient<ISmsSender, AuthMessageSender>();

        }

but obviously not when I run the webjob. So, when I try to access anything in the context, I get this exception (after setting context = new context()):

System.InvalidOperationException occurred
  HResult=0x80131509
  Message=No database provider has been configured for this DbContext. A provider can be configured by overriding the DbContext.OnConfiguring method or by using AddDbContext on the application service provider. If AddDbContext is used, then also ensure that your DbContext type accepts a DbContextOptions<TContext> object in its constructor and passes it to the base constructor for DbContext.
  Source=Microsoft.EntityFrameworkCore

It seems to me, it's because I'm not doing any configuration on the DbContext, but I'm not sure. Is there a better way to accomplish this? Or am I missing something small?

Edit: This is the program.cs of my webjob (minus the emailing functionality, which is cluttery):

private static MooodDbContext _context;

        // Please set the following connection strings in app.config for this WebJob to run:
        // AzureWebJobsDashboard and AzureWebJobsStorage

        private static void Main()
        {
            _context = new MooodDbContext(new DbContextOptions<MooodDbContext>());

            var host = new JobHost();

            EmailAllHerds();

            host.RunAndBlock();

            EmailAllHerds();
        }

Solution

  • Couple of assumptions that i made here

    • web job is a console App built on .net core

    So you will have Program.cs file with a main method. So in your

    Program.cs

    class Program {
       // declare a field to store config values
       private readonly IConfigurationRoot _configuration;
       // Declare a constructor 
       public Program()
       {
           var builder = new ConfigurationBuilder()
                .SetBasePath(environment.BasePath)
                .AddJsonFile($"appsettings.json", true, true)
                .AddJsonFile($"appsettings.{environment.EnvironmentName}.json", true, true)
                .AddEnvironmentVariables();
    
            _configuration = builder.Build();
       }
     }
      public static void Main(string[] args)
      {
         var program = new Program();
         var serviceCollection = new ServiceCollection();
         program.ConfigureServices(serviceCollection);           
    
      }
    
        private void ConfigureServices(IServiceCollection services)
        {
           // now here you can resolve your DbContext similar to web
          services.AddDbContext<MooodDbContext>(options =>options.UseSqlServer(_configuration.GetConnectionString("MooodConnection")));
        }
    }