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

# Quartz.Extensions.Hosting

A new package Quartz.Extensions.Hosting(opens new window) was created with the help of Andrew Lock(opens new window) . 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(opens new window) 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(opens new window) . 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(opens new window) 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)
Grab it from downloads page.