Skip to content

Configuring storage providers

Configure in-memory, EF Core, LinqToDB and Redis storage and own their schemas correctly.

2 min read

In-memory

builder.Services.AddMyAppJobs(options => options.UseInMemory());

This is also the default when no storage is selected. It is non-durable and single-node but implements recurring, graph and fair-queue behavior for development and tests.

Entity Framework Core

dotnet add package Immediate.Jobs.EntityFrameworkCore --prerelease

Prefer a dedicated, application-owned JobsDbContext so the jobs schema stays separate from your application’s business model. The context can still use the same physical database if that suits your deployment:

// The application's business data uses its own context and model.
builder.Services.AddDbContext<AppDbContext>(db =>
	db.UseNpgsql(appConnectionString));

// Immediate.Jobs uses a separate context and model.
builder.Services.AddDbContextFactory<JobsDbContext>(db =>
	db.UseNpgsql(jobsConnectionString));       // PostgreSQL
// db.UseSqlite(jobsConnectionString);       // SQLite
// db.UseSqlServer(jobsConnectionString);    // SQL Server

builder.Services.AddMyAppJobs(options =>
	options.UseEntityFrameworkCore<JobsDbContext>());

public sealed class AppDbContext(DbContextOptions<AppDbContext> options) : DbContext(options)
{
	public DbSet<Order> Orders => Set<Order>();
}

public sealed class Order
{
	public Guid Id { get; set; }
}

public sealed class JobsDbContext(DbContextOptions<JobsDbContext> options) : DbContext(options)
{
	protected override void OnModelCreating(ModelBuilder modelBuilder)
	{
		base.OnModelCreating(modelBuilder);
		modelBuilder.AddImmediateJobs(schema: "background"); // omit the schema for SQLite
	}
}

AddImmediateJobs configures the EF Core model but does not ship or apply migration files. Generate an application-owned migration explicitly after adding the model:

dotnet ef migrations add CreateImmediateJobsSchema 
	--context JobsDbContext 
	--output-dir Migrations/ImmediateJobs

Run the command from the startup project. If the context and startup application are in different projects, also pass the appropriate --project and --startup-project paths. Apply the generated migration through the application’s normal deployment process, or locally with:

dotnet ef database update --context JobsDbContext

The generated migration creates the seven Immediate.Jobs tables, indexes and constraints. EnsureCreated is appropriate only for samples or disposable databases. Using an existing business DbContext is supported, but it couples the jobs schema to that model.

LinqToDB

dotnet add package Immediate.Jobs.LinqToDB --prerelease
var dataOptions = new DataOptions().UsePostgreSQL(connectionString);
// new DataOptions().UseSQLite(connectionString);
// new DataOptions().UseSqlServer(connectionString);

await dataOptions.CreateImmediateJobsSchemaAsync(
	schema: "background", // must be null for SQLite
	CancellationToken.None
);

builder.Services.AddMyAppJobs(options =>
	options.UseLinqToDB(dataOptions, schema: "background"));

The application owns DataOptions, the matching ADO.NET driver and schema lifecycle. The helper supports SQLite (without a named schema), PostgreSQL and SQL Server and creates the tables and indexes for a fresh database.

Redis

dotnet add package Immediate.Jobs.Redis --prerelease

Pass a configuration string when Jobs should own the connection:

builder.Services.AddMyAppJobs(options => options.UseRedis(
	"localhost:6379",
	redis =>
	{
		redis.Database = 1;
		redis.KeyPrefix = "billing-jobs";
	}
));

Or pass an application-owned IConnectionMultiplexer; the provider will not dispose it. The configuration-string overload owns and disposes its connection. Database defaults to -1 (server default), and KeyPrefix defaults to immediate-jobs. Prefixes cannot contain braces because the provider adds its own Redis Cluster hash tag for atomic Lua operations.

Redis always selects distributed mode and supports queue plus recurring capabilities. It does not support graph workflows or fair queues.