Quartz.NETQuartz.NET
Home
Features
Blog
Discussions
NuGet
GitHub
Home
Features
Blog
Discussions
NuGet
GitHub
  • Getting Started

    • Overview
    • Quartz 4 Quick Start
    • Tutorial
      • Using Quartz
      • Jobs And Triggers
      • More About Jobs & JobDetails
      • Job Data
      • More About Triggers
      • Querying Jobs and Triggers
      • Simple Triggers
      • Cron Triggers
      • RecurrenceTrigger
      • Time and TimeProvider
      • Trigger and Job Listeners
      • Scheduler Listeners
      • Job Execution Middleware
      • Job Stores
      • Configuration, Resource Usage and Building a Scheduler
      • Building a Scheduler Without a Host
      • Clustering
      • Execution Groups
      • Node Affinity (Preferred Node)
      • Testing
    • Configuration Reference
    • JSON Configuration
    • Cron Expression Reference
    • Multi-Tenancy
    • Frequently Asked Questions
    • Best Practices
    • Before You Go Live
    • Operating a Cluster
    • Log Events
    • Tenancy Patterns
    • Database Schema
    • Database Schema Changes
    • Migration Guide
    • Troubleshooting
  • How To's
    • One-Off Job
    • Rescheduling Jobs
    • Retrying Failed Jobs
    • Multiple Triggers
    • Job Template
    • Running Quartz under Aspire
    • Quartz.NET with Wolverine
    • Embedding Quartz in a Library
    • Running under an External Leader Election
    • Publishing Trimmed and Native AOT
    • Extending Quartz: what is open, what is closed, and how to ask
    • A Job Store of Your Own
    • A Driver Delegate for a New Database
    • Persisting a Custom Trigger Type
    • A Lock Handler of Your Own
  • Packages

    • Quartz Core Additions

      • Jobs
      • Serialization (System.Text.Json)
      • JSON Serialization
      • Plugins
    • Integrations

      • Aspire Integration
      • ASP.NET Core Integration
      • HTTP API
      • HTTP Client
      • Dashboard
      • Hosted Services Integration
      • Microsoft DI Integration
      • Multiple Schedulers with Microsoft DI
      • Observability
      • Redis Lock Handler
      • TimeZoneConverter Integration
    • 3rd Party Plugins for Quartz
  • Quartz 3.x

    • Getting Started

      • Quartz 3 Quick Start
      • Tutorial
        • Using Quartz
        • Library Overview
        • Jobs And Triggers
        • More About Jobs
        • More About Triggers
        • Execution Groups
        • Node Affinity (Preferred Node)
        • Simple Triggers
        • Cron Triggers
        • RecurrenceTrigger
        • Trigger and Job Listeners
        • Scheduler Listeners
        • Job Stores
        • Tuning the Scheduler
        • Configuration, Resource Usage and SchedulerFactory
        • Advanced (Enterprise) Features
      • Configuration Reference
      • JSON Configuration
      • Multi-Tenancy
      • Frequently Asked Questions
      • Best Practices
      • Tenancy Patterns
      • Troubleshooting
      • API Documentation
      • Database Schema
      • Database Schema Changes
      • Migration Guide
      • Miscellaneous Features
    • How To's

      • One-Off Job
      • Multiple Triggers
      • Job Template
      • Using the CronTrigger
      • Rescheduling Jobs
    • Packages

      • Quartz Core Additions

        • Dashboard
        • Jobs
        • Serialization (System.Text.Json)
        • Serialization (Newtonsoft Json.NET)
        • Plugins
      • Integrations

        • ASP.NET Core Integration
        • Hosted Services Integration
        • Microsoft DI Integration
        • Multiple Schedulers with Microsoft DI
        • OpenTelemetry Integration
        • OpenTracing Integration
        • Redis Lock Handler
        • TimeZoneConverter Integration
      • 3rd Party Plugins for Quartz
  • Old Releases

    • Quartz 2.x
      • Quartz 2 Quick Start
      • Tutorial
        • Lesson 1: Using Quartz
        • Lesson 2: Jobs And Triggers
        • Lesson 3: More About Jobs & JobDetails
        • Lesson 4: More About Triggers
        • Lesson 5: SimpleTrigger
        • Lesson 6: CronTrigger
        • Lesson 7: TriggerListeners and JobListeners
        • Lesson 8: SchedulerListeners
        • Lesson 9: JobStores
        • Lesson 10: Configuration, Resource Usage and SchedulerFactory
        • Lesson 11: Advanced (Enterprise) Features
        • Lesson 12: Miscellaneous Features of Quartz
        • CronTrigger Tutorial
      • Configuration Reference
      • Migration Guide
      • API Documentation
    • Quartz 1.x
      • Tutorial
        • Lesson 1: Using Quartz
        • Lesson 2: Jobs And Triggers
        • Lesson 3: More About Jobs & JobDetails
        • Lesson 4: More About Triggers
        • Lesson 5: SimpleTrigger
        • Lesson 6: CronTrigger
        • Lesson 7: TriggerListeners and JobListeners
        • Lesson 8: SchedulerListeners
        • Lesson 9: JobStores
        • Lesson 10: Configuration, Resource Usage and SchedulerFactory
        • Lesson 11: Advanced (Enterprise) Features
        • Lesson 12: Miscellaneous Features of Quartz
      • API Documentation
  • License

This release concentrates on tweaking the DI story and fixing some found dependency issues.

  • Quartz.Extensions.Hosting
  • Refining DI integration API
    • Options pattern
    • ScheduleJob
    • AddCalendar
  • Microsoft SQL Server
    • Full Framework
    • .NET Core
    • Query plan cache pollution fix
  • GitHub Issues

Quartz.Extensions.Hosting

A new package Quartz.Extensions.Hosting was created with the help of Andrew Lock. If you are using generic host and you don't need ASP.NET specific functionality like health checks, you can switch to this new package to reduce dependencies.

Refining DI integration API

Some work was done to improve the MS DI integration API.

Options pattern

Now the API uses options pattern properly and you can attach your own configurators to alter QuartzOptions.

// we can use options pattern to support hooking your own configuration
// because we don't use service registration api
// we need to manally 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));
        }
    });

ScheduleJob

A new shorthand was created to quickly define a job with trigger using a single call.

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")
);

AddCalendar

You can now add calendars using the DI API.

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)
);

Microsoft SQL Server

Now Quartz no longer has hard dependency on Microsoft.Data.SqlClient package. Full framework defaults now back to same behavior as it was with Quartz 3.0 (using built-in System.Data.SqlClient driver).

Full Framework

You can use either one of the two providers, SqlServer (default) or SystemDataSqlClient. Former uses System.Data.SqlClient and latter the new Microsoft.Data.SqlClient package. If you choose to use the new package, make sure you have the NuGet package installed.

.NET Core

You need to ensure you have Microsoft.Data.SqlClient package installed.

Query plan cache pollution fix

There was an important fix for SQL Server where varying text parameter sizes caused query plan cache pollution. Now when no parameter size is defined for string parameter, default value of 4000 will be used. This problem has been present since the beginning.

GitHub Issues

BREAKING CHANGES

  • Remove dependency on Microsoft.Data.SqlClient (#912)
  • LogContext moved from Quartz namespace to Quartz.Logging namespace (#915)
  • For Full Framework, System.Data.SqlClient is again the default provider, Microsoft.Data can be used via provider MicrosoftDataSqlClient (#916)

NEW FEATURE

  • Introduce separate Quartz.Extensions.Hosting (#911)
  • You can now schedule job and trigger in MS DI integration with single .ScheduleJob call (#943)
  • Support adding calendars to MS DI via AddCalendar<T> (#945)

FIXES

  • Revert change in 3.1: CronExpression/cron trigger throwing NotImplementedException when calculating final fire time (#905)
  • Use 2.1 as the minimum version for the .NET Platform Extensions (#923)
  • ServiceCollection.AddQuartz() should register default ITypeLoadHelper if none supplied (#924)
  • SqlServer AdoJobStore SqlParameter without text size generates pressure on server (#939)
  • DbProvider initialization logic should also read quartz.config (#951)
  • LoggingJobHistoryPlugin and LoggingTriggerHistoryPlugin names are null with IoC configuration (#926)
  • Improve options pattern to allow better custom configuration story (#955)
See download and installation instructions.
Help us by improving this page!
Last Updated: 9/3/26, 1:13 PM
Contributors: Marko Lahma, Claude Fable 5.1