You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
## Solve SQLite Concurrency & Performance in EF Core
9
9
10
-
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?
10
+
Tired of `"database is locked"` (`SQLITE_BUSY`) errors in your multi-threaded .NET app? Need to insert data faster than the standard `SaveChanges()` allows?
11
11
12
12
**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.
|**❌ Complex Retry Logic:** You need to build resilience yourself. |**✅ Built-In Resilience:** Exponential backoff retry and robust connection management out of the box. |
34
-
|**❌ High Memory Usage:**Large operations are inefficient. |**✅ Optimized Performance:**Streamlined operations for speed and lower memory overhead. |
33
+
|**❌ Complex Retry Logic:** You need to build resilience yourself. |**✅ Built-In Resilience:** Exponential backoff retry with full jitter, handling all `SQLITE_BUSY*` variants correctly. |
34
+
|**❌ EF DbContext not thread-safe:**Sharing one context across concurrent tasks throws. |**✅ IDbContextFactory support:**`AddConcurrentSqliteDbContextFactory<T>` wires up the correct EF Core pattern for concurrent workloads. |
Run your app. Concurrent writes are now serialized automatically, and reads are parallel. Your existing DbContext, models, and LINQ queries work unchanged.
58
59
59
-
Next, explore high-performance bulk inserts or fine-tune the configuration.
60
+
Your existing `DbContext`, models, and LINQ queries work unchanged. Concurrent writes are serialized automatically. Reads execute in parallel.
60
61
61
62
---
62
63
@@ -74,105 +75,150 @@ Next, explore high-performance bulk inserts or fine-tune the configuration.
74
75
75
76
---
76
77
77
-
## Advanced Usage & Performance
78
-
High-Performance Bulk Operations
78
+
## Usage Examples
79
+
80
+
### Bulk Operations
81
+
79
82
```csharp
80
-
// Process massive datasets with speed and reliability
// Bulk insert with automatic transaction management and write serialization
86
+
await_context.BulkInsertOptimizedAsync(posts);
87
87
}
88
88
```
89
89
90
-
Optimized Concurrent Operations
90
+
### Concurrent Workloads — use `IDbContextFactory`
91
+
92
+
A `DbContext` is not thread-safe and must not be shared across concurrent operations. Inject `IDbContextFactory<T>` and call `CreateDbContext()` to give each concurrent flow its own independent instance:
93
+
91
94
```csharp
92
-
// Multiple threads writing simultaneously just work
|`BusyTimeout`| 30 s |`PRAGMA busy_timeout` — SQLite retries lock acquisition internally for this duration before surfacing `SQLITE_BUSY`. |
165
+
|`MaxRetryAttempts`| 3 | Application-level retry attempts after `SQLITE_BUSY*`, with exponential backoff and full jitter. |
166
+
|`CommandTimeout`| 300 s | EF Core SQL command timeout. |
167
+
|`WalAutoCheckpoint`| 1000 pages |`PRAGMA wal_autocheckpoint` — triggers a passive checkpoint after this many WAL frames (~4 MB). Set to `0` to disable. |
168
+
|`SynchronousMode`|`Normal`|`PRAGMA synchronous` — durability vs. write-speed trade-off. `Normal` is recommended for WAL mode. |
169
+
|`UpgradeTransactionsToImmediate`|`true`| Rewrites `BEGIN` to `BEGIN IMMEDIATE` to prevent `SQLITE_BUSY_SNAPSHOT` mid-transaction. |
170
+
171
+
> **Note:**`Cache=Shared` in the connection string is incompatible with WAL mode and will throw `ArgumentException` at startup. Connection pooling (`Pooling=true`) is enabled automatically and is the correct alternative.
172
+
137
173
---
138
174
139
175
## FAQ
140
-
Q: How does it achieve 10x faster bulk inserts?
141
-
A: Through intelligent batching, optimized transaction management, and reduced database round-trips. We process data in optimal chunks and minimize overhead at every layer.
142
176
143
-
Q: Will this work with my existing queries and LINQ code?
144
-
A: Absolutely. Your existing query patterns, includes, and projections work unchanged while benefiting from improved read concurrency and reduced locking.
177
+
**Q: How does it achieve 10x faster bulk inserts?**
178
+
A: Through intelligent batching, optimized transaction management, and reduced database round-trips. Data is processed in optimal chunks with all PRAGMAs applied once per connection.
179
+
180
+
**Q: Will this work with my existing queries and LINQ code?**
181
+
A: Yes. Existing DbContext types, models, and LINQ queries work unchanged.
145
182
146
-
Q: Is there a performance cost for the thread safety?
147
-
A: Less than 1ms per write operation—negligible compared to the performance gains from optimized bulk operations and parallel reads.
183
+
**Q: Is there a performance cost for the write serialization?**
184
+
A: Under 1ms per write operation. The semaphore overhead is negligible compared to actual I/O, and the WAL-mode PRAGMA tuning more than compensates for it on read-heavy workloads.
148
185
149
-
Q: How does memory usage compare to standard EF Core?
150
-
A: Our optimized operations use significantly less memory, especially for bulk inserts and large queries, thanks to streaming and intelligent caching strategies.
186
+
**Q: Why do I need `IDbContextFactory` for concurrent workloads?**
187
+
A: EF Core's `DbContext` is not thread-safe by design — it tracks state per instance. `IDbContextFactory<T>` creates an independent context per concurrent flow, which both satisfies EF Core's threading model and lets `ThreadSafeEFCore.SQLite` serialize the writes correctly at the SQLite level.
151
188
152
-
Q: Can I still use SQLite-specific features?
153
-
A: Yes. All SQLite features remain accessible while gaining our performance and concurrency enhancements.
189
+
**Q: Does this work on network filesystems?**
190
+
A: No. SQLite WAL mode requires all connections to be on the same physical host. Do not use this library against a database on NFS, SMB, or any other network-mounted path. Use a client/server database for multi-host deployments.
// 3. Remove Cache=Shared from any connection string that contains it.
165
209
166
-
Monitor Performance Gains → Watch your operation times drop significantly
210
+
// 4. Remove any custom retry or locking logic — the library handles it.
211
+
```
167
212
168
-
## 🏗️ System Requirements
169
-
.NET 10.0+
213
+
---
170
214
171
-
Entity Framework Core 10.0+
215
+
## System Requirements
172
216
173
-
SQLite 3.35.0+
217
+
- .NET 10.0+
218
+
- Entity Framework Core 10.0+
219
+
- Microsoft.Data.Sqlite 10.0+
220
+
- SQLite 3.35.0+
174
221
175
-
## 📄 License
176
-
EntityFrameworkCore.Sqlite.Concurrency is licensed under the MIT License. Free for commercial use, open source projects, and enterprise applications.
222
+
## License
177
223
178
-
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.
224
+
EntityFrameworkCore.Sqlite.Concurrency is licensed under the MIT License. Free for commercial use, open-source projects, and enterprise applications.
0 commit comments