Getting started
XactJobs lets you schedule and run background jobs with full database transaction support using Entity Framework Core. Jobs are saved alongside your business data and only execute if your transaction commits: no “ghost” jobs on rollback.
It supports SQL Server, PostgreSQL, MySQL, Oracle and SQLite, on .NET 8, 9 and 10. XactJobs uses EF Core 9 on .NET 8 and 9, and EF Core 10 on .NET 10, so your database provider has to support that version. For MySQL, see which provider to use.
1. Install the package
Section titled “1. Install the package”dotnet add package XactJobsYour app also needs the EF Core provider of its database, registered as usual. The provider isn’t part of XactJobs:
// Microsoft.EntityFrameworkCore.SqlServerbuilder.Services.AddDbContext<UserDbContext>(options => options.UseSqlServer(connectionString));// Npgsql.EntityFrameworkCore.PostgreSQLbuilder.Services.AddDbContext<UserDbContext>(options => options.UseNpgsql(connectionString));// .NET 9 and 10: MySql.EntityFrameworkCorebuilder.Services.AddDbContext<UserDbContext>(options => options.UseMySQL(connectionString));
// .NET 8 and 9: Pomelo.EntityFrameworkCore.MySqlbuilder.Services.AddDbContext<UserDbContext>(options => options.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString)));With the official provider, SaveChanges doesn’t start a transaction on its own. See MySQL before you go further.
// Oracle.EntityFrameworkCorebuilder.Services.AddDbContext<UserDbContext>(options => options.UseOracle(connectionString));// Microsoft.EntityFrameworkCore.Sqlitebuilder.Services.AddDbContext<UserDbContext>(options => options.UseSqlite(connectionString));2. Create the tables
Section titled “2. Create the tables”For a new installation, run the install script for your database. It creates the latest schema: the job table, the history and the periodic jobs.
sql/install/xact-jobs-sqlserver.sql creates the tables in the XactJobs schema.
Run it with QUOTED_IDENTIFIER and ANSI_NULLS on, which are SqlClient’s and SSMS’s defaults (sqlcmd needs -I): the job table has a filtered index.
sql/install/xact-jobs-postgresql.sql creates the tables in the xact_jobs schema.
The job table is a high-churn queue: see the autovacuum settings recommended for it.
sql/install/xact-jobs-mysql.sql creates the xact_jobs_ tables. XactJobs needs MySQL 8.0 or later.
sql/install/xact-jobs-oracle.sql creates the XACT_JOBS_ tables. XactJobs needs Oracle 12c or later.
sql/install/xact-jobs-sqlite.sql creates the xact_jobs_ tables.
All the scripts are in sql/. To upgrade an existing installation, run the versioned scripts instead: see Upgrading.
Or use EF migrations
Section titled “Or use EF migrations”Instead of the scripts, you can include the XactJobs entities in your EF migrations:
protected override void OnModelCreating(ModelBuilder modelBuilder){ modelBuilder.ApplyXactJobsConfigurations(Database.ProviderName, excludeFromMigrations: false); // <--- key part here
// Apply your entity configurations...}And then create the migration like you normally would:
dotnet ef migrations add XactJobsTables3. Configure startup
Section titled “3. Configure startup”Add the entity configurations to your DbContext:
public class UserDbContext : DbContext{ public UserDbContext(DbContextOptions<UserDbContext> options) : base(options) { }
// Your DbSets...
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.ApplyXactJobsConfigurations(Database.ProviderName);
// Apply your entity configurations... }}Register XactJobs in Program.cs. The workers run as hosted services in your app:
// This registers 2 workers for the default queuebuilder.Services.AddXactJobs<UserDbContext>(options =>{ options.WithPriorityQueue(); // optional (2 additional workers) options.WithLongRunningQueue(); // optional (2 additional workers)});All the options are in the configuration reference.
4. Enqueue a job
Section titled “4. Enqueue a job”A job is a public method. Enqueue it on your DbContext, next to your business data, and save. JobEnqueue and the other methods
are extension methods in the XactJobs namespace (using XactJobs;):
public static class Greeter{ public static void Say(string message) => Console.WriteLine(message);}// ... other business logicdbContext.JobEnqueue( () => Greeter.Say("Fire-and-forget!"));
dbContext.SaveChanges();The job is a row in the same transaction as your changes. If the transaction commits, a worker runs it; if it rolls back, the job doesn’t exist.
- Read Jobs for what a job method can be, and how instance methods get their dependencies.
- Read A job is a unit of work: the worker saves a job’s database changes, not the job.
- Add the dashboard to see and manage the jobs.