Class SchedulerEnlistmentExtensions
- Namespace
- Quartz
- Assembly
- Quartz.dll
Lets application code hand its own ADO.NET connection and transaction to the persistent job store, so that scheduling operations take part in a unit of work the application already owns.
public static class SchedulerEnlistmentExtensions
- Inheritance
-
SchedulerEnlistmentExtensions
- Inherited Members
Remarks
Requires the job store to be configured to accept enlisted transactions -
Configure(o => o.AcceptEnlistedTransactions = true) on the persistent store builder, or
quartz.jobStore.acceptEnlistedTransactions. Without it the job store keeps opening its own
connection and managing its own transaction, and enlisting throws rather than being ignored.
Enlisting is the only way to take part: an ambient TransactionScope on its own is not enough, because a connection the job store opens for itself is deliberately kept out of it. Open the connection inside the scope and enlist that, which also keeps the transaction from having to be promoted to a distributed one.
The enlistment flows with the current asynchronous context, so it must be established in the
same scope as the scheduler calls it should cover - the same rule that applies to
TransactionScope, and for the same reason. In particular,
establishing it inside an async helper does not carry it back out to the caller.
While the enlistment is in effect the job store holds its locks in the caller's transaction, so they are only released once that transaction completes. Keep enlisted transactions short: a long running one blocks trigger acquisition, the misfire handler and cluster check-in.
await using var tx = await dbContext.Database.BeginTransactionAsync();
dbContext.Add(entity);
await dbContext.SaveChangesAsync();
using (scheduler.EnlistTransaction(tx.GetDbTransaction()))
{
await scheduler.ScheduleJob(job, trigger);
await tx.CommitAsync();
}
Methods
EnlistConnection(IScheduler, DbConnection, DbTransaction?)
Makes the persistent job store use the given connection, and optionally the given transaction, for every operation performed on the current asynchronous flow until the returned scope is disposed.
public static IDisposable EnlistConnection(this IScheduler scheduler, DbConnection connection, DbTransaction? transaction = null)
Parameters
schedulerISchedulerThe scheduler whose job store should use the connection.
connectionDbConnectionThe connection to use. Opened if it is not open already.
transactionDbTransactionThe transaction to enlist in, if any.
Returns
- IDisposable
A scope that ends the enlistment when disposed. Dispose it after committing, so that any scheduling change the job store recorded is signalled to the scheduler once it is visible.
Remarks
Pass only a connection when the transaction is an ambient TransactionScope the connection is already enlisted in. Sharing the one connection is what keeps such a scope from being promoted to a distributed transaction, which providers like Npgsql do not support at all. That the connection is enlisted is established here rather than assumed, so a driver that cannot join the scope is refused instead of written through.
Exceptions
- SchedulerException
A TransactionScope is current and the connection's driver implements no EnlistTransaction(Transaction), so the connection cannot join it —
Microsoft.Data.Sqliteis the shipped case. Enlist a DbTransaction of the connection's own instead.
EnlistTransaction(IScheduler, DbTransaction)
Makes the persistent job store use the given transaction, and the connection it belongs to, for every operation performed on the current asynchronous flow until the returned scope is disposed.
public static IDisposable EnlistTransaction(this IScheduler scheduler, DbTransaction transaction)
Parameters
schedulerISchedulerThe scheduler whose job store should join the transaction.
transactionDbTransactionThe transaction to join. Must still be associated with a connection.
Returns
- IDisposable
A scope that ends the enlistment when disposed. Dispose it after committing, so that any scheduling change the job store recorded is signalled to the scheduler once it is visible.