Rask.SQLite.Browser
0.23.1-alpha.0.66
See the version list below for details.
dotnet add package Rask.SQLite.Browser --version 0.23.1-alpha.0.66
NuGet\Install-Package Rask.SQLite.Browser -Version 0.23.1-alpha.0.66
<PackageReference Include="Rask.SQLite.Browser" Version="0.23.1-alpha.0.66" />
<PackageVersion Include="Rask.SQLite.Browser" Version="0.23.1-alpha.0.66" />
<PackageReference Include="Rask.SQLite.Browser" />
paket add Rask.SQLite.Browser --version 0.23.1-alpha.0.66
#r "nuget: Rask.SQLite.Browser, 0.23.1-alpha.0.66"
#:package Rask.SQLite.Browser@0.23.1-alpha.0.66
#addin nuget:?package=Rask.SQLite.Browser&version=0.23.1-alpha.0.66&prerelease
#tool nuget:?package=Rask.SQLite.Browser&version=0.23.1-alpha.0.66&prerelease
Rask.SQLite.Browser
A real SQLite database inside a browser WebAssembly app — the same Microsoft.Data.Sqlite, and the same
Entity Framework Core on top of it, that you would run on a server — persisted across reloads.
Why
A WASM app has no filesystem that survives a reload. SQLite still runs there: the native e_sqlite3 is
linked into the app at publish, and the database file lives in the runtime's in-memory filesystem. What is
missing is durability, and one owner. This package supplies both.
- Restored before anything opens it. A hosted service reads the newest snapshot out of IndexedDB and
writes the file during
StartAsync, so a service registered after it finds a populated database rather than an empty one. - Written back on an interval and on page-hide, through SQLite's Online Backup API
(
Rask.SQLite.Snapshots) — never an unsafe file copy of a database someone might be writing to. - Owned by exactly one tab. Every tab has its own copy of the in-memory filesystem, so two of them would hold two divergent databases and the last to snapshot would silently overwrite the other. A Web Lock elects one owner; the others run unpersisted and say so.
Use
builder.Services.AddRaskBrowserSqlite("app");
builder.Services.AddDbContextFactory<AppDbContext>(o =>
o.UseSqlite(BrowserSqlite.ConnectionString("app")));
// From here on, nothing is browser-specific:
builder.Services.AddRaskJobs<AppDbContext>();
Register it before anything that opens the database — registration order is start order.
builder.Services.AddRaskBrowserSqlite("app", o =>
{
o.SnapshotInterval = 10.Seconds; // the real durability window
o.Retain = 2; // each snapshot costs a full database in quota
});
Full-text search
Ranked, word-aware search over the local database works the way it does on the server. Add
Rask.SQLite.EntityFrameworkCore and put
UseRaskFullTextSearch() after the plain UseSqlite — it registers only what search needs, none of the
server's pragmas:
builder.Services.AddDbContextFactory<AppDbContext>(o => o
.UseSqlite(BrowserSqlite.ConnectionString("app"))
.UseRaskFullTextSearch());
var hits = await db.Set<Post>().Search(query).Take(20).ToListAsync(); // best match first
Declare the index with Rask.Data's HasFullTextSearch(p => new { p.Title, p.Body }) and apply migrations
(Database.MigrateAsync()): the FTS5 index is built by a migration, and EnsureCreated creates none. FTS5 is
compiled into the SQLite build that is linked into the WebAssembly app.
What to know before you rely on it
- Entity Framework Core needs its three assemblies rooted in a trimmed build. EF Core builds its model
and queries by reflection, so trimmed without roots it fails with a
MissingMethodExceptionat the first EF call. Add<TrimmerRootAssembly Include="…"/>forMicrosoft.EntityFrameworkCore,Microsoft.EntityFrameworkCore.RelationalandMicrosoft.EntityFrameworkCore.Sqlite, and suppress EF's ownIL2026;IL2104(plusWASM0001for the SQLite natives).Microsoft.Data.Sqlite, this package, Rask.Data and Rask.SQLite.EntityFrameworkCore are trim-safe and need nothing.PublishTrimmed=falsealso works, at a much larger download. - The durability window is the snapshot interval, not the page-hide flush. The browser does not wait
for a
pagehidehandler, so a force-closed or crashed tab loses whatever changed since the last tick. - Snapshots live in IndexedDB, which is evictable. The owning tab asks the browser to exempt the
origin (
navigator.storage.persist()) at startup; a refusal is logged and changes nothing else. Chromium decides on engagement without prompting, Firefox prompts — so an app that would rather choose its moment setso.RequestPersistentStorage = falseand callsIStorageEstimator.RequestPersistAsync()from a user-gesture handler instead. - Non-owner tabs are not read-only — they are separate. They get their own empty in-memory database
and never persist, which looks like data loss unless you say otherwise. Inject
BrowserSqliteOwnershipand tell the user:await ownership.Resolvedgives the answer, andownership.IsOwnerisnullwhile the election is still running so a normal boot never flashes a banner. When the owner closes,await ownership.Availablecompletes so you can offer a reload — reloading is what takes ownership, since a waiting tab already opened its own empty database and the file cannot be swapped under live connections. Proxying a non-owner's writes to the owner is not implemented. - Snapshots cost their full database size in the origin's storage quota, times
Retain. - Add
<NoWarn>$(NoWarn);WASM0001</NoWarn>if you build with warnings as errors: the SQLite native build reports two varargs functions (sqlite3_config,sqlite3_db_config) that WASM cannot call. Neither is reached on the normal open/query/update paths.
Links
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-browser1.0 is compatible. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. net11.0 is compatible. net11.0-browser1.0 is compatible. |
-
net10.0
- Microsoft.Data.Sqlite (>= 10.0.12)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.12)
- Microsoft.Extensions.Hosting.Abstractions (>= 10.0.12)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.12)
- Rask.SQLite.Snapshots (>= 0.23.1-alpha.0.66)
- SQLitePCLRaw.bundle_e_sqlite3 (>= 3.0.5)
-
net10.0-browser1.0
- Microsoft.Data.Sqlite (>= 10.0.12)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.12)
- Microsoft.Extensions.Hosting.Abstractions (>= 10.0.12)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.12)
- Rask.SQLite.Snapshots (>= 0.23.1-alpha.0.66)
- SQLitePCLRaw.bundle_e_sqlite3 (>= 3.0.5)
-
net11.0
- Microsoft.Data.Sqlite (>= 10.0.12)
- Rask.SQLite.Snapshots (>= 0.23.1-alpha.0.66)
- SQLitePCLRaw.bundle_e_sqlite3 (>= 3.0.5)
-
net11.0-browser1.0
- Microsoft.Data.Sqlite (>= 10.0.12)
- Rask.SQLite.Snapshots (>= 0.23.1-alpha.0.66)
- SQLitePCLRaw.bundle_e_sqlite3 (>= 3.0.5)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.23.1-alpha.0.84 | 29 | 9/25/2026 |
| 0.23.1-alpha.0.82 | 28 | 9/25/2026 |
| 0.23.1-alpha.0.81 | 34 | 9/25/2026 |
| 0.23.1-alpha.0.80 | 22 | 9/25/2026 |
| 0.23.1-alpha.0.79 | 32 | 9/25/2026 |
| 0.23.1-alpha.0.78 | 27 | 9/25/2026 |
| 0.23.1-alpha.0.76 | 35 | 9/25/2026 |
| 0.23.1-alpha.0.74 | 26 | 9/25/2026 |
| 0.23.1-alpha.0.72 | 29 | 9/25/2026 |
| 0.23.1-alpha.0.70 | 35 | 9/25/2026 |
| 0.23.1-alpha.0.69 | 39 | 9/25/2026 |
| 0.23.1-alpha.0.68 | 41 | 9/25/2026 |
| 0.23.1-alpha.0.67 | 45 | 9/25/2026 |
| 0.23.1-alpha.0.66 | 33 | 9/24/2026 |
| 0.23.1-alpha.0.65 | 36 | 9/24/2026 |
| 0.23.1-alpha.0.64 | 29 | 9/24/2026 |
| 0.23.1-alpha.0.62 | 29 | 9/24/2026 |
| 0.23.1-alpha.0.61 | 34 | 9/24/2026 |
| 0.23.1-alpha.0.50 | 34 | 9/24/2026 |
| 0.23.0 | 88 | 9/18/2026 |