Overview
This article explains how to set the waiting time (timeout) for Entity Framework Core (EF Core) when executing SQL against a database. By extending the timeout value, you can prevent intentional disconnections (TimeoutException) during long-running aggregation tasks or bulk update processes that exceed the default limit (usually 30 seconds).
Specifications (Input/Output)
- Input: Timeout duration in seconds (int).
- Output: A
DbContextinstance with the configuration applied. - Prerequisites: .NET 6.0 or higher. Works with relational database providers such as SQLite, SQL Server, and PostgreSQL. This example uses
Microsoft.EntityFrameworkCore.Sqlite.
Basic Usage
You can configure the timeout using an action delegate in the second argument of the provider configuration methods (e.g., UseSqlite, UseSqlServer) within the DbContextOptionsBuilder.
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite("Data Source=app.db", options =>
{
// Set timeout to 180 seconds (3 minutes)
options.CommandTimeout(180);
});
}
Full Code Example
The following is a complete example of configuring the timeout value when initializing a DbContext in a console application. If you are using a DI container (AddDbContext), the notation is the same, though the configuration will be located in Program.cs.
The Microsoft.EntityFrameworkCore.Sqlite package is required. dotnet add package Microsoft.EntityFrameworkCore.Sqlite
using System;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
public class Program
{
public static async Task Main()
{
// Use the Context with the timeout setting applied
using (var context = new LongRunningContext())
{
// Create the database
await context.Database.EnsureDeletedAsync();
await context.Database.EnsureCreatedAsync();
Console.WriteLine($"Current Timeout: {context.Database.GetCommandTimeout()} seconds");
// Execute standard data operations
context.Products.Add(new Product { Name = "Heavy Calculation Item" });
await context.SaveChangesAsync();
Console.WriteLine("Database operation completed.");
}
}
}
// DbContext definition
public class LongRunningContext : DbContext
{
public LongRunningContext() { }
public LongRunningContext(DbContextOptions<LongRunningContext> options) : base(options) { }
public DbSet<Product> Products => Set<Product>();
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
// Only configure if not already configured (to prioritize DI container settings)
if (!optionsBuilder.IsConfigured)
{
var connectionString = "Data Source=app.db";
optionsBuilder.UseSqlite(connectionString, sqliteOptions =>
{
// Key Point:
// Set the command execution timeout to 180 seconds (3 minutes)
// The default is typically 30 seconds
sqliteOptions.CommandTimeout(180);
});
// Log output for verification
optionsBuilder.LogTo(Console.WriteLine, Microsoft.Extensions.Logging.LogLevel.Information);
}
}
}
// Entity definition
public class Product
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
}
Customization Points
- DI Container Configuration (ASP.NET Core, etc.): When using
AddDbContextinProgram.cs, write it as follows:C#builder.Services.AddDbContext<LongRunningContext>(options => options.UseSqlite(connectionString, providerOptions => providerOptions.CommandTimeout(180) ) ); - Temporary Changes: If you want to extend the timeout only for a specific heavy task rather than the entire application, you can change it dynamically in the code (see Advanced Application).
Important Notes
- Default Values: Most providers default to 30 seconds. If not set, queries taking longer than 30 seconds will fail with
OperationCanceledExceptionorSqlException. - Overly Long Settings: Setting an unnecessarily long time (or 0 for infinite) can prevent database locks from being released, potentially blocking access for other users. Apply this only where necessary.
- Difference from Connection Timeout:
CommandTimeoutis the “wait time for a query to execute.” This is different from the “wait time to connect to the DB,” which is defined in the connection string asConnect Timeout. Do not confuse the two.
Advanced Application
Changing the Timeout for a Specific Process
This method allows you to extend the time only for a specific heavy report generation process without changing the settings for the entire Context.
using (var context = new LongRunningContext())
{
// Temporarily change the timeout for this context instance to 5 minutes
context.Database.SetCommandTimeout(300);
// Execute a time-consuming aggregation process
// await context.Database.ExecuteSqlRawAsync("EXEC VeryHeavyStoredProcedure");
// You can revert it to the default afterward (or simply dispose of the Context)
context.Database.SetCommandTimeout(null); // Setting to null reverts to default
}
Conclusion
Use OnConfiguring or AddDbContext for global settings, and Database.SetCommandTimeout for local adjustments.
This setting is effective for batch processing or large data migrations where you know a process will take time.
Specify the CommandTimeout within the options lambda expression of UseSqlite or UseSqlServer.
