Quartz.Extensions.DependencyInjection 3.13.1

Prefix Reserved
dotnet add package Quartz.Extensions.DependencyInjection --version 3.13.1                
NuGet\Install-Package Quartz.Extensions.DependencyInjection -Version 3.13.1                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Quartz.Extensions.DependencyInjection" Version="3.13.1" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Quartz.Extensions.DependencyInjection --version 3.13.1                
#r "nuget: Quartz.Extensions.DependencyInjection, 3.13.1"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Quartz.Extensions.DependencyInjection as a Cake Addin
#addin nuget:?package=Quartz.Extensions.DependencyInjection&version=3.13.1

// Install Quartz.Extensions.DependencyInjection as a Cake Tool
#tool nuget:?package=Quartz.Extensions.DependencyInjection&version=3.13.1                

Quartz.Extensions.DependencyInjection provides integration with Microsoft Dependency Injection.

::: tip Quartz 3.1 or later required. :::

Installation

You need to add NuGet package reference to your project which uses Quartz.

Install-Package Quartz.Extensions.DependencyInjection

Using

You can add Quartz configuration by invoking an extension method AddQuartz on IServiceCollection. The configuration building wraps various configuration properties with strongly-typed API. You can also configure properties using standard .NET Core appsettings.json inside configuration section Quartz.

::: tip Quartz.Extensions.Hosting allows you to have a background service for your application that handles starting and stopping the scheduler. :::

Example appsettings.json

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "Quartz": {
    "quartz.scheduler.instanceName": "Quartz ASP.NET Core Sample Scheduler"
  }
}

DI aware job factories

Quartz comes with two built-in alternatives for job factory which can be configured via either calling UseMicrosoftDependencyInjectionJobFactory or UseMicrosoftDependencyInjectionScopedJobFactory (deprecated).

::: tip As of Quartz.NET 3.7 all jobs are created as scoped and MS DI is configured by default. There shouldn't be need to call UseMicrosoftDependencyInjection* overloads. :::

Job instance construction

By default Quartz will try to resolve job's type from container and if there's no explicit registration Quartz will use ActivatorUtilities to construct job and inject it's dependencies via constructor. Job should have only one public constructor.

Persistent job stores

The scheduling configuration will be checked against database and updated accordingly every time your application starts and schedule is being evaluated.

::: warning When using persistent job store, make sure you define job and trigger names for your scheduling so that existence checks work correctly against the data you already have in your database.

Using API to configure triggers and jobs without explicit job identity configuration will cause jobs and triggers to have different generated name each time configuration is being evaluated.

With persistent job stores it's best practice to always declare at least job and trigger name. Omitting the group for them will produce same default group value for every invocation. :::

Example Startup.ConfigureServices configuration

public void ConfigureServices(IServiceCollection services)
{
    // base configuration from appsettings.json
    services.Configure<QuartzOptions>(Configuration.GetSection("Quartz"));

    // if you are using persistent job store, you might want to alter some options
    services.Configure<QuartzOptions>(options =>
    {
        options.Scheduling.IgnoreDuplicates = true; // default: false
        options.Scheduling.OverWriteExistingData = true; // default: true
    });

    services.AddQuartz(q =>
    {
        // handy when part of cluster or you want to otherwise identify multiple schedulers
        q.SchedulerId = "Scheduler-Core";
        
        // we take this from appsettings.json, just show it's possible
        // q.SchedulerName = "Quartz ASP.NET Core Sample Scheduler";
        
        // or for scoped service support like EF Core DbContext
        // q.UseMicrosoftDependencyInjectionScopedJobFactory();
        
        // these are the defaults
        q.UseSimpleTypeLoader();
        q.UseInMemoryStore();
        q.UseDefaultThreadPool(tp =>
        {
            tp.MaxConcurrency = 10;
        });

        // quickest way to create a job with single trigger is to use ScheduleJob
        // (requires version 3.2)
        q.ScheduleJob<ExampleJob>(trigger => trigger
            .WithIdentity("Combined Configuration Trigger")
            .StartAt(DateBuilder.EvenSecondDate(DateTimeOffset.UtcNow.AddSeconds(7)))
            .WithDailyTimeIntervalSchedule(x => x.WithInterval(10, IntervalUnit.Second))
            .WithDescription("my awesome trigger configured for a job with single call")
        );

        // you can also configure individual jobs and triggers with code
        // this allows you to associated multiple triggers with same job
        // (if you want to have different job data map per trigger for example)
        q.AddJob<ExampleJob>(j => j
            .StoreDurably() // we need to store durably if no trigger is associated
            .WithDescription("my awesome job")
        );

        // here's a known job for triggers
        var jobKey = new JobKey("awesome job", "awesome group");
        q.AddJob<ExampleJob>(jobKey, j => j
            .WithDescription("my awesome job")
        );

        q.AddTrigger(t => t
            .WithIdentity("Simple Trigger")    
            .ForJob(jobKey)
            .StartNow()
            .WithSimpleSchedule(x => x.WithInterval(TimeSpan.FromSeconds(10)).RepeatForever())
            .WithDescription("my awesome simple trigger")
        );

        q.AddTrigger(t => t
            .WithIdentity("Cron Trigger")    
            .ForJob(jobKey)
            .StartAt(DateBuilder.EvenSecondDate(DateTimeOffset.UtcNow.AddSeconds(3)))
            .WithCronSchedule("0/3 * * * * ?")
            .WithDescription("my awesome cron trigger")
        );

        // you can add calendars too (requires version 3.2)
        const string calendarName = "myHolidayCalendar";
        q.AddCalendar<HolidayCalendar>(
            name: calendarName,
            replace: true,
            updateTriggers: true,
            x => x.AddExcludedDate(new DateTime(2020, 5, 15))
        );

        q.AddTrigger(t => t
            .WithIdentity("Daily Trigger")
            .ForJob(jobKey)
            .StartAt(DateBuilder.EvenSecondDate(DateTimeOffset.UtcNow.AddSeconds(5)))
            .WithDailyTimeIntervalSchedule(x => x.WithInterval(10, IntervalUnit.Second))
            .WithDescription("my awesome daily time interval trigger")
            .ModifiedByCalendar(calendarName)
        );
        
        // also add XML configuration and poll it for changes
        q.UseXmlSchedulingConfiguration(x =>
        {
            x.Files = new[] { "~/quartz_jobs.config" };
            x.ScanInterval = TimeSpan.FromSeconds(2);
            x.FailOnFileNotFound = true;
            x.FailOnSchedulingError = true;
        });

        // convert time zones using converter that can handle Windows/Linux differences
        q.UseTimeZoneConverter();
        
        // auto-interrupt long-running job
        q.UseJobAutoInterrupt(options =>
        {
            // this is the default
            options.DefaultMaxRunTime = TimeSpan.FromMinutes(5);
        });
        q.ScheduleJob<SlowJob>(
            triggerConfigurator => triggerConfigurator
                .WithIdentity("slowJobTrigger")
                .StartNow()
                .WithSimpleSchedule(x => x.WithIntervalInSeconds(5).RepeatForever()),
            jobConfigurator => jobConfigurator
                .WithIdentity("slowJob")
                .UsingJobData(JobInterruptMonitorPlugin.JobDataMapKeyAutoInterruptable, true)
                // allow only five seconds for this job, overriding default configuration
                .UsingJobData(JobInterruptMonitorPlugin.JobDataMapKeyMaxRunTime, TimeSpan.FromSeconds(5).TotalMilliseconds.ToString(CultureInfo.InvariantCulture)));

        // add some listeners
        q.AddSchedulerListener<SampleSchedulerListener>();
        q.AddJobListener<SampleJobListener>(GroupMatcher<JobKey>.GroupEquals(jobKey.Group));
        q.AddTriggerListener<SampleTriggerListener>();

        // example of persistent job store using JSON serializer as an example
        /*
        q.UsePersistentStore(s =>
        {
            s.PerformSchemaValidation = true; // default
            s.UseProperties = true; // preferred, but not default
            s.RetryInterval = TimeSpan.FromSeconds(15);
            s.UseSqlServer(sqlServer =>
            {
                sqlServer.ConnectionString = "some connection string";
                // this is the default
                sqlServer.TablePrefix = "QRTZ_";
            });
            s.UseJsonSerializer();
            s.UseClustering(c =>
            {
                c.CheckinMisfireThreshold = TimeSpan.FromSeconds(20);
                c.CheckinInterval = TimeSpan.FromSeconds(10);
            });
        });
        */
    });
	
	// we can use options pattern to support hooking your own configuration
	// because we don't use service registration api, 
	// we need to manually ensure the job is present in DI
	services.AddTransient<ExampleJob>();
				
	services.Configure<SampleOptions>(Configuration.GetSection("Sample"));
	services.AddOptions<QuartzOptions>()
		.Configure<IOptions<SampleOptions>>((options, dep) =>
		{
			if (!string.IsNullOrWhiteSpace(dep.Value.CronSchedule))
			{
				var jobKey = new JobKey("options-custom-job", "custom");
				options.AddJob<ExampleJob>(j => j.WithIdentity(jobKey));
				options.AddTrigger(trigger => trigger
					.WithIdentity("options-custom-trigger", "custom")
					.ForJob(jobKey)
					.WithCronSchedule(dep.Value.CronSchedule));
			}
		});	
		
    // Quartz.Extensions.Hosting allows you to fire background service that handles scheduler lifecycle
    services.AddQuartzHostedService(options =>
    {
        // when shutting down we want jobs to complete gracefully
        options.WaitForJobsToComplete = true;
    });
}
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (74)

Showing the top 5 NuGet packages that depend on Quartz.Extensions.DependencyInjection:

Package Downloads
Quartz.Extensions.Hosting

Quartz.NET Generic Host integration; Quartz Scheduling Framework for .NET

OpenIddict.Quartz

Quartz.NET integration package for OpenIddict.

Elsa.Activities.Temporal.Quartz

Elsa is a set of workflow libraries and tools that enable lean and mean workflowing capabilities in any .NET Core application. This package provides a Quartz timer provider.

Volo.Abp.Quartz

Package Description

Aiwins.Rocket.Quartz

Package Description

GitHub repositories (10)

Showing the top 5 popular GitHub repositories that depend on Quartz.Extensions.DependencyInjection:

Repository Stars
abpframework/abp
Open-source web application framework for ASP.NET Core! Offers an opinionated architecture to build enterprise software solutions with best practices on top of the .NET. Provides the fundamental infrastructure, cross-cutting-concern implementations, startup templates, application modules, UI themes, tooling and documentation.
dotnetcore/Util
Util是一个.Net平台下的应用框架,旨在提升中小团队的开发能力,由工具类、分层架构基类、Ui组件,配套代码生成模板,权限等组成。
openiddict/openiddict-core
Flexible and versatile OAuth 2.0/OpenID Connect stack for .NET
DGP-Studio/Snap.Hutao
实用的开源多功能原神工具箱 🧰 / Multifunctional Open-source Genshin Impact Toolkit 🧰
oskardudycz/EventSourcing.NetCore
Examples and Tutorials of Event Sourcing in .NET
Version Downloads Last updated
3.13.1 732,354 11/2/2024
3.13.0 1,639,065 8/10/2024
3.12.0 187,553 8/3/2024
3.11.0 870,414 7/7/2024
3.10.0 247,028 6/26/2024
3.9.0 1,225,352 5/9/2024
3.8.1 2,123,351 2/17/2024
3.8.0 2,417,476 11/18/2023
3.7.0 2,361,474 8/4/2023
3.6.3 888,815 6/25/2023
3.6.2 3,374,080 2/25/2023
3.6.1 4,281 2/25/2023
3.6.0 739,272 1/29/2023
3.5.0 3,771,698 9/18/2022
3.4.0 4,232,027 3/27/2022
3.3.3 4,589,511 8/1/2021
3.3.2 1,172,651 4/9/2021
3.3.1 47,268 4/8/2021
3.3.0 18,497 4/7/2021
3.2.4 1,774,221 1/19/2021
3.2.3 711,324 10/31/2020
3.2.2 50,326 10/19/2020
3.2.1 11,677 10/18/2020
3.2.0 32,971 10/2/2020
3.1.0 266,364 7/24/2020
0.4.0 4,067 4/27/2020
0.3.0 1,813 3/25/2020
0.2.0 1,408 2/17/2020
0.1.1 3,258 11/15/2018
0.1.0 5,010 11/14/2018