SQLite
The Shiny.DocumentDb.Sqlite package provides the default SQLite-backed document store. It is the recommended provider for mobile, desktop, embedded, and single-process scenarios — full LINQ-to-SQL translation, JSON indexes, spatial queries via R*Tree, hot backup, and a ClearAllAsync shortcut.
When to Use
Section titled “When to Use”- Mobile (.NET MAUI iOS/Android) and desktop apps
- Single-process embedded storage
- Local-first / offline-capable apps
- Blazor WebAssembly when you need full SQL features (paired with
SQLitePCLRaw.bundle_wasm)
If you need encryption at rest, use SQLCipher instead. For browser persistence without a native binary, see IndexedDB.
Installation
Section titled “Installation”dotnet add package Shiny.DocumentDb.Sqlite-
Direct instantiation
using Shiny.DocumentDb.Sqlite;// Quick setupvar store = new SqliteDocumentStore("Data Source=mydata.db");// Full optionsvar store = new SqliteDocumentStore(new DocumentStoreOptions{DatabaseProvider = new SqliteDatabaseProvider("Data Source=mydata.db")}); -
Dependency injection
using Shiny.DocumentDb;using Shiny.DocumentDb.Sqlite;services.AddDocumentStore(opts =>{opts.DatabaseProvider = new SqliteDatabaseProvider("Data Source=mydata.db");});
Storage Layout
Section titled “Storage Layout”CREATE TABLE IF NOT EXISTS "documents" ( Id TEXT NOT NULL, TypeName TEXT NOT NULL, Data TEXT NOT NULL, CreatedAt TEXT NOT NULL, UpdatedAt TEXT NOT NULL, PRIMARY KEY (Id, TypeName));The Data column stores raw JSON text. Property access translates to json_extract(Data, '$.path'). Deep Upsert runs server-side via SQLite’s json_patch() (RFC 7396).
Backup
Section titled “Backup”SqliteDocumentStore.Backup(path) uses the SQLite Online Backup API — the store stays usable during the copy.
var store = new SqliteDocumentStore("Data Source=mydata.db");await store.Backup("/path/to/backup.db");Backup is not on the IDocumentStore interface — it lives on the concrete SqliteDocumentStore type. Marked [UnsupportedOSPlatform("browser")] so it produces a compiler warning when called from browser-targeted code.
Clear All
Section titled “Clear All”SqliteDocumentStore.ClearAllAsync() deletes every document across every table, including spatial sidecar tables. Useful for tearing down test fixtures or signing a user out of a local-first app.
var store = new SqliteDocumentStore("Data Source=mydata.db");await store.ClearAllAsync();Spatial Queries
Section titled “Spatial Queries”SQLite uses R*Tree virtual tables for WithinRadius, WithinBoundingBox, and NearestNeighbors. Sidecar tables are created and synced automatically on insert/update/upsert/remove/clear. Register the GeoPoint property at setup:
var store = new SqliteDocumentStore(new DocumentStoreOptions{ DatabaseProvider = new SqliteDatabaseProvider("Data Source=mydata.db")}.MapSpatialProperty<Restaurant>(r => r.Location));See Spatial Queries for the full API.
Blazor WebAssembly
Section titled “Blazor WebAssembly”The SQLite provider is WASM-compatible when paired with SQLitePCLRaw.bundle_wasm:
- WAL pragma skipped on
OperatingSystem.IsBrowser() - Spatial disabled (R*Tree unavailable in WASM-compiled SQLite)
- Backup unsupported in the browser
- Use
Data Source=:memory:or Emscripten OPFS-mounted paths
For most WASM scenarios, the lighter IndexedDB provider is recommended.
Indexes
Section titled “Indexes”await store.CreateIndexAsync<User>(u => u.Name);// CREATE INDEX IF NOT EXISTS idx_json_User_name// ON "documents" (json_extract(Data, '$.name'))// WHERE TypeName = 'User';Indexes are partial by type so multiple types sharing the same table do not pay for each other’s indexes. See Indexes & Transactions.
- Reader-many / writer-one concurrency model.
- Identifiers are quoted with
"— types namedOrder,Group,Userwork without collision. Upsertis RFC 7396 deep merge viajson_patch.- Raw SQL queries use
json_extract(Data, '$.path').