IndexedDB (Blazor WASM)
The Shiny.DocumentDb.IndexedDb package provides an IndexedDB-backed document store for Blazor WebAssembly applications. It implements the full IDocumentStore interface using JavaScript interop — no native dependencies, no file system access required.
When to Use
Section titled “When to Use”- Blazor WebAssembly apps that need client-side persistent storage
- Offline-capable progressive web apps (PWAs)
- Browser-based apps where you want the same document store API as your server/mobile code
Installation
Section titled “Installation”dotnet add package Shiny.DocumentDb.IndexedDb-
Register with dependency injection in your Blazor WASM
Program.cs:using Shiny.DocumentDb.IndexedDb;builder.Services.AddSingleton(new IndexedDbDocumentStoreOptions { DatabaseName = "MyAppDb" });builder.Services.AddSingleton<IDocumentStore, IndexedDbDocumentStore>();Or with full options:
builder.Services.AddSingleton(new IndexedDbDocumentStoreOptions{DatabaseName = "MyAppDb",Version = 1}.MapTypeToStore<User>() // dedicated object store.MapTypeToStore<Order>("orders") // explicit store name);builder.Services.AddSingleton<IDocumentStore, IndexedDbDocumentStore>(); -
Inject and use
IDocumentStorein your components:@inject IDocumentStore Store@code {private List<User> users = new();protected override async Task OnInitializedAsync(){users = (await Store.Query<User>().ToList()).ToList();}private async Task AddUser(){var user = new User { Name = "Alice", Age = 25 };await Store.Insert(user);users.Add(user);}}
Options Reference
Section titled “Options Reference”| Property | Type | Default | Description |
|---|---|---|---|
DatabaseName | string | (required) | The name of the IndexedDB database |
Version | int | 1 | IndexedDB database version. Increment when adding new object stores |
StoreName | string | "documents" | Default object store for unmapped types |
TypeNameResolution | TypeNameResolution | ShortName | How type names are stored |
JsonSerializerOptions | JsonSerializerOptions? | null | JSON serialization settings |
UseReflectionFallback | bool | true | Set to false for AOT safety |
Logging | Action<string>? | null | Diagnostic callback |
Store-Per-Type Mapping
Section titled “Store-Per-Type Mapping”Similar to table-per-type mapping in SQL providers, you can map document types to dedicated IndexedDB object stores:
builder.Services.AddSingleton(new IndexedDbDocumentStoreOptions{ DatabaseName = "MyAppDb"}.MapTypeToStore<User>() // auto-derived store name .MapTypeToStore<Order>("orders") // explicit store name .MapTypeToStore<Sensor>(s => s.DeviceKey) // custom Id property);builder.Services.AddSingleton<IDocumentStore, IndexedDbDocumentStore>();Supported Operations
Section titled “Supported Operations”The IndexedDB provider supports the full IDocumentStore API:
Insert,Update,Upsert,BatchInsertGet,Remove,ClearSetProperty,RemovePropertyGetDiff(JSON patch diffing)Query<T>()fluent LINQ queries (Where, OrderBy, Paginate, Select, aggregates)Count<T>()RunInTransaction(operations are batched in a single IndexedDB transaction)
Not Supported
Section titled “Not Supported”- Raw SQL queries —
Query<T>(string whereClause)andQueryStream<T>(string whereClause)throwNotSupportedException. Use the LINQ-basedQuery<T>()overload instead. - Spatial queries — IndexedDB does not support R*Tree or GeoJSON indexes.
How It Works
Section titled “How It Works”Under the hood, the provider:
- Opens an IndexedDB database with the configured name and version
- Creates object stores (with a
typeNameindex) during theupgradeneededevent - Stores documents as
{ key, id, typeName, data, createdAt, updatedAt }records - Uses the composite key
"{TypeName}:{Id}"as the IndexedDB key path - Queries load all documents of a type via the
typeNameindex, then apply LINQ predicates client-side
All IndexedDB operations are performed through a JavaScript ES module (shiny-indexeddb.js) bundled as a static web asset.
SQLite in Blazor WASM
Section titled “SQLite in Blazor WASM”If you need SQL-level query features (raw WHERE clauses, JSON indexes, spatial queries), the existing SQLite provider is also WASM-compatible when paired with SQLitePCLRaw.bundle_wasm:
- WAL pragma is automatically skipped on
OperatingSystem.IsBrowser() - Spatial (R*Tree) is automatically disabled in the browser
Backup()is marked[UnsupportedOSPlatform("browser")]- Use
Data Source=:memory:or Emscripten OPFS-mounted paths
The IndexedDB provider is lighter (no native WASM SQLite binary) and simpler for most client-side storage scenarios. Choose SQLite-in-WASM only when you need its advanced query capabilities.
Versioning
Section titled “Versioning”When you add new type-to-store mappings, increment Version so that the upgradeneeded event fires and creates the new object stores:
opts.Version = 2; // was 1, now creating a new storeopts.MapTypeToStore<NewType>();IndexedDB handles the schema migration automatically — existing data in other stores is preserved.