liveBook · Manning

Locking

As explained in ASP.NET Core in Action, 3e

Database locking is a concurrency-control technique that restricts simultaneous access to shared database state.

Database locking coordinates clustered background tasks by allowing only one application instance to handle a trigger and run its associated job. section 34.3.3

In a clustered Quartz.NET deployment:

  • Quartz.NET persists jobs and triggers in a shared database and uses its locking primitives to prevent duplicate handling. section 34.3.3
  • SQLite can store persistence data but cannot provide the locking primitives required for clustering. section 34.3.3
  • The required Quartz.NET tables must be created separately, using supplied database scripts or an EF Core migration. section 34.3.3
Listing 34.13 Enabling persistence and clustering for Quartz.NET
using Quartz;
 
IHost host = Host.CreateDefaultBuilder(args)
    .ConfigureServices((hostContext, services) =>             #1
    {
        var connectionString = Configuration                  #2
            .GetConnectionString("DefaultConnection");        #2
 
        services.AddQuartz(q =>                                       
        {
            q.SchedulerId = "AUTO";                           #3
 
            q. UseMicrosoftDependencyInjectionJobFactory();      
                         
            q.UsePersistentStore(s =>                         #4
            {
               s.UseSqlServer(connectionString);              #5
               s.UseClustering();                             #6
               s.UseProperties = true;                        #7
               s.UseJsonSerializer();                         #7
            });
    
            var jobKey = new JobKey("Update_exchange_rates");        
            q.AddJob<UpdateExchangeRatesJob>(opts =>                 
                opts.WithIdentity(jobKey));                          
 
            q.AddTrigger(opts => opts                                
                .ForJob(jobKey)                                      
                .WithIdentity(jobKey.Name + " trigger")              
                .StartNow()                                          
                .WithSimpleSchedule(x => x                           
                    .WithInterval(TimeSpan.FromMinutes(5))           
                    .RepeatForever())                                
            );
        });
 
        services.AddQuartzHostedService(
            q => q.WaitForJobsToComplete = true);
    })
    .Build();
host.Run();
#1 Configuration is identical for both ASP.NET Core apps and worker services.
#2 Obtains the connection string for your database from configuration
#3 Each instance of your app must have a unique SchedulerId. AUTO takes care of this for you.
#4 Enables database persistence for the Quartz.NET scheduler data
#5 Stores the scheduler data in a SQL Server (or LocalDb) database
#6 Enables clustering between multiple instances of your app
#7 Adds the recommended configuration for job persistence

Shows the Quartz.NET configuration that combines a persistent SQL Server store with clustering. section 34.3.3

How ASP.NET Core in Action, 3e covers it

How deep it goes
Explains the operational purpose and database limitations but stops short of describing lock internals.
Examples
Uses Quartz.NET jobs and triggers, SQL Server persistence, a clustering configuration, and an EF Core schema migration.
What it assumes
Assumes Quartz.NET persistence, a supported database, and manually created Quartz.NET tables.
What you can do after
Operate clustered Quartz.NET services that coordinate trigger handling through a shared database.
How it connects
Connects database locking with Quartz.NET, persistence, clustering, background tasks, and horizontal scaling.

Also explained in

Compare how 18 books explain locking →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of ASP.NET Core in Action, 3e. The section links point to the parts of the book it draws on.