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
ci: add rich SEO-optimized release body to deploy workflow
GitHub Release description now includes the exact exception strings
developers search for (SQLITE_BUSY, database is locked, SQLITE_BUSY_SNAPSHOT),
installation snippet, problems table, quick-setup code, benchmark results,
and links to all documentation pages.
## What's New in v${{ steps.get_version.outputs.VERSION }}
93
+
94
+
### Channel-Based Write Queue
95
+
96
+
Replaces the per-database `SemaphoreSlim(1,1)` with a `Channel<IWriteRequest>`-based write queue backed by a single background writer.
97
+
98
+
Under concurrent write load, `SemaphoreSlim.Release()` wakes all N waiters simultaneously — N-1 immediately go back to sleep. This thundering-herd pattern causes CPU spikes and unfair scheduling. A `Channel<T>` parks callers in FIFO order and drains them one at a time. No wakeup storm. No API change required.
99
+
100
+
- New `SqliteWriteQueue` internal class owns the channel and the background writer loop
101
+
- New `WriteQueueCapacity` option: `null` = unbounded (default), integer = bounded with `BoundedChannelFullMode.Wait` for back-pressure
102
+
- Zero breaking changes
103
+
104
+
### Bug Fixes
105
+
106
+
- `ThreadSafeSqliteContext.ExecuteWriteAsync` was ignoring registered options (always using defaults). Fixed via interceptor lookup.
107
+
- `BulkInsertSafeAsync` used `Skip/Take` in a loop — O(n^2) complexity. Replaced with `Chunk(1000)`.
108
+
- `BulkInsertSafeAsync` did not call `ChangeTracker.Clear()` between batches — memory grew linearly with entity count. Now cleared after each batch.
109
+
110
+
### netstandard 2.0 Support
111
+
112
+
The connection and queue layer now targets `netstandard2.0`. EF Core-dependent APIs remain `net10.0`-only.
113
+
114
+
### Real BenchmarkDotNet Results
115
+
116
+
Measured on .NET 10.0.2 / Windows 11 / Intel i7-13700K:
117
+
118
+
| Operation | Standard EF Core | This Package | Ratio |
Or search **EntityFrameworkCore.Sqlite.Concurrency** on [NuGet.org](https://www.nuget.org/packages/EntityFrameworkCore.Sqlite.Concurrency).
132
+
133
+
---
134
+
135
+
## Problems This Solves
136
+
137
+
| Error | Cause | Fix |
138
+
|---|---|---|
139
+
| `SQLite Error 5: 'database is locked'` (SQLITE_BUSY) | Multiple concurrent writers | Channel-based write queue — one writer at a time, all others wait in FIFO order |
140
+
| `SQLite Error 5: 'database is locked'` (SQLITE_BUSY_SNAPSHOT, code 517) | WAL read snapshot stale mid-transaction | `BEGIN IMMEDIATE` upgrade + full operation restart |
141
+
| `A second operation was started on this context instance` | Shared `DbContext` across concurrent tasks | `IDbContextFactory<T>` registration |
142
+
| Slow bulk inserts | One `SaveChanges` per entity | `BulkInsertOptimizedAsync` — batched writes, ChangeTracker cleared per batch |
- [Concurrent EF Core patterns](https://github.com/CornerstoneCode/EntityFrameworkCore.Sqlite.Concurrency/blob/main/docs/concurrent-efcore-patterns.md)
178
+
- [Performance and WAL tuning guide](https://github.com/CornerstoneCode/EntityFrameworkCore.Sqlite.Concurrency/blob/main/docs/performance-guide.md)
179
+
- [Migration guide from plain UseSqlite](https://github.com/CornerstoneCode/EntityFrameworkCore.Sqlite.Concurrency/blob/main/docs/migration-guide.md)
0 commit comments