Skip to content

High-performance EntityFrameworkCore.Sqlite extension for concurrent reads and writes. Fix EFCore SQLite "database is locked" and "busy" errors with 10x faster bulk inserts and parallel read scaling. The definitive thread-safe solution for SQLite performance and concurrency in dotnet

License

Notifications You must be signed in to change notification settings

CornerstoneCode/EntityFrameworkCore.Sqlite.Concurrency

Repository files navigation

EntityFrameworkCore.Sqlite.Concurrency

NuGet Version Downloads License: MIT .NET 10

🚀 Solve SQLite Concurrency & Performance

Tired of "database is locked" (SQLITE_BUSY) errors in your multi-threaded .NET 10 app? Need to insert data faster than the standard SaveChanges() allows?

EntityFrameworkCore.Sqlite.Concurrency is a high-performance add-on to Microsoft.EntityFrameworkCore.Sqlite that adds automatic transaction upgrades, write serialization, and production-ready optimizations, making SQLite robust and fast for enterprise applications.

→ Get started in one line:

// Replace this:
options.UseSqlite("Data Source=app.db");

// With this:
options.UseSqliteWithConcurrency("Data Source=app.db");

Guaranteed 100% write reliability and up to 10x faster bulk operations.


Why Choose This Package?

Problem with Standard EF Core SQLite Our Solution & Benefit
❌ Concurrency Errors: SQLITE_BUSY / database is locked under load. ✅ Automatic Write Serialization: BEGIN IMMEDIATE transactions and optional app-level locking eliminate locking errors.
❌ Slow Bulk Inserts: Linear SaveChanges() performance. ✅ Intelligent Batching: ~10x faster bulk inserts with optimized transactions and PRAGMAs.
❌ Read Contention: Reads can block behind writes. ✅ True Parallel Reads: Automatic WAL mode + optimized connection pooling for non-blocking reads.
❌ Complex Retry Logic: You need to build resilience yourself. ✅ Built-In Resilience: Exponential backoff retry and robust connection management out of the box.
❌ High Memory Usage: Large operations are inefficient. ✅ Optimized Performance: Streamlined operations for speed and lower memory overhead.

Simple Installation

  1. Install the package:
# Package Manager
Install-Package EntityFrameworkCore.Sqlite.Concurrency

OR

# .NET CLI
dotnet add package EntityFrameworkCore.Sqlite.Concurrency
  1. Update your DbContext configuration (e.g., in Program.cs):
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqliteWithConcurrency("Data Source=app.db"));

Run your app. Concurrent writes are now serialized automatically, and reads are parallel. Your existing DbContext, models, and LINQ queries work unchanged.

Next, explore high-performance bulk inserts or fine-tune the configuration.


Performance Benchmarks: Real Results

Operation Standard EF Core SQLite EntityFrameworkCore.Sqlite.Concurrency Performance Gain
Bulk Insert (10,000 records) ~4.2 seconds ~0.8 seconds 5.25x faster
Bulk Insert (100,000 records) ~42 seconds ~4.1 seconds 10.2x faster
Concurrent Reads (50 threads) ~8.7 seconds ~2.1 seconds 4.1x faster
Mixed Read/Write Workload ~15.3 seconds ~3.8 seconds 4.0x faster
Memory Usage (100k operations) ~425 MB ~285 MB 33% less memory

Benchmark environment: .NET 10, Windows 11, Intel i7-13700K, 32GB RAM


Advanced Usage & Performance

High-Performance Bulk Operations

// Process massive datasets with speed and reliability
public async Task PerformDataMigrationAsync(List<LegacyData> legacyRecords)
{
    var modernRecords = legacyRecords.Select(ConvertToModernFormat).ToList();
    
    // Optimized bulk insert with automatic transaction management and locking
    await _context.BulkInsertOptimizedAsync(modernRecords);
}

Optimized Concurrent Operations

// Multiple threads writing simultaneously just work
public async Task ProcessHighVolumeWorkload()
{
    var writeTasks = new[]
    {
        ProcessUserRegistrationAsync(newUser1),
        ProcessUserRegistrationAsync(newUser2),
        LogAuditEventsAsync(events)
    };
    
    await Task.WhenAll(writeTasks); // All complete successfully without "database is locked"
}

Factory Pattern for Maximum Control

// Create performance-optimized contexts on demand
public async Task<TResult> ExecuteHighPerformanceOperationAsync<TResult>(
    Func<DbContext, Task<TResult>> operation)
{
    using var context = ThreadSafeFactory.CreateContext<AppDbContext>(
        "Data Source=app.db",
        options => options.MaxRetryAttempts = 5);
    
    return await context.ExecuteWithRetryAsync(operation, maxRetries: 5);
}

Configuration

Maximize your SQLite performance with these optimized settings:

services.AddDbContext<AppDbContext>(options =>
    options.UseSqliteWithConcurrency(
        "Data Source=app.db",
        concurrencyOptions =>
        {
            concurrencyOptions.MaxRetryAttempts = 3;          // Automatic retry for SQLITE_BUSY
            concurrencyOptions.BusyTimeout = TimeSpan.FromSeconds(30);
            concurrencyOptions.CommandTimeout = 300;          // 5-minute timeout for large operations
            concurrencyOptions.WalAutoCheckpoint = 1000;      // Optimized WAL management
        }));

FAQ

Q: How does it achieve 10x faster bulk inserts? A: Through intelligent batching, optimized transaction management, and reduced database round-trips. We process data in optimal chunks and minimize overhead at every layer.

Q: Will this work with my existing queries and LINQ code? A: Absolutely. Your existing query patterns, includes, and projections work unchanged while benefiting from improved read concurrency and reduced locking.

Q: Is there a performance cost for the thread safety? A: Less than 1ms per write operation—negligible compared to the performance gains from optimized bulk operations and parallel reads.

Q: How does memory usage compare to standard EF Core? A: Our optimized operations use significantly less memory, especially for bulk inserts and large queries, thanks to streaming and intelligent caching strategies.

Q: Can I still use SQLite-specific features? A: Yes. All SQLite features remain accessible while gaining our performance and concurrency enhancements.

Migration: From Slow to Fast

Upgrade path for existing applications:

Add NuGet Package → Install-Package EntityFrameworkCore.Sqlite.Concurrency

Update DbContext Configuration → Change UseSqlite() to UseSqliteWithConcurrency()

Replace Bulk Operations → Change loops with SaveChanges() to BulkInsertOptimizedAsync()

Remove Custom Retry Logic → Our built-in retry handles everything optimally

Monitor Performance Gains → Watch your operation times drop significantly

🏗️ System Requirements

.NET 10.0+

Entity Framework Core 10.0+

SQLite 3.35.0+

📄 License

EntityFrameworkCore.Sqlite.Concurrency is licensed under the MIT License. Free for commercial use, open source projects, and enterprise applications.

Stop compromising on SQLite performance. Get enterprise-grade speed and 100% reliability with EntityFrameworkCore.Sqlite.Concurrency—the only EF Core extension that fixes SQLite's limitations while unlocking its full potential.

About

High-performance EntityFrameworkCore.Sqlite extension for concurrent reads and writes. Fix EFCore SQLite "database is locked" and "busy" errors with 10x faster bulk inserts and parallel read scaling. The definitive thread-safe solution for SQLite performance and concurrency in dotnet

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published