![]() |
VOOZH | about |
dotnet add package BlazorEssentials.IndexedDb --version 4.0.2
NuGet\Install-Package BlazorEssentials.IndexedDb -Version 4.0.2
<PackageReference Include="BlazorEssentials.IndexedDb" Version="4.0.2" />
<PackageVersion Include="BlazorEssentials.IndexedDb" Version="4.0.2" />Directory.Packages.props
<PackageReference Include="BlazorEssentials.IndexedDb" />Project file
paket add BlazorEssentials.IndexedDb --version 4.0.2
#r "nuget: BlazorEssentials.IndexedDb, 4.0.2"
#:package BlazorEssentials.IndexedDb@4.0.2
#addin nuget:?package=BlazorEssentials.IndexedDb&version=4.0.2Install as a Cake Addin
#tool nuget:?package=BlazorEssentials.IndexedDb&version=4.0.2Install as a Cake Tool
This is a Blazor library for accessing IndexedDB, it uses Jake Archibald's idb library for handling access to IndexedDB API.
It maps as closely to the browser IndexedDB API as possible, but in a .NET way, so you can use public documentation.
This library is a fork of BlazorIndexedDbJs, which in turn is a fork of Blazor.IndexedDB.
The original library was licensed under the MIT License, and this library is as well.
IndexedDb instead of IDB (the later conflicts with C# interface naming conventions)Asyncidb remotely, resulting in smaller package sizesYou can see a demo of using IndexedDbDatabase and ViewModels together in our Sample App.
NET 8.0 or newer
Install-Package BlazorEssentials.IndexedDb
or
dotnet add package BlazorEssentials.IndexedDb
Add the following to your _Imports.razor file:
@using CloudNimble.BlazorEssentials.IndexedDb
IndexedDBDatabase classThis file should feel very similar to a DbContext class. Here is a basic implementation, using one of my favorite childhood restaurants as an example:
Data/TheSpaghettiFactoryDb.cs
using Microsoft.JSInterop;
using CloudNimble.BlazorEssentials.IndexedDb;
namespace BlazorEssentials.IndexedDb.Demo.Data
{
public class TheFactoryDb: IndexedDbDatabase
{
public IndexedDbObjectStore Employees { get; set;}
public TheSpaghettiFactoryDb(IJSRuntime jsRuntime): base(jsRuntime)
{
Name = "TheSpaghettiFactory";
Version = 1;
}
}
}
Or you can customize it with attributes. In the below example:
firstName property for the FiredEmployees IndexedDbObjectStore (table)Data/TheSpaghettiFactoryDb.cs
using Microsoft.JSInterop;
using CloudNimble.BlazorEssentials.IndexedDb;
namespace BlazorEssentials.IndexedDb.Demo.Data
{
public class TheSpaghettiFactoryDb: IndexedDbDatabase
{
[ObjectStore(Name = "FiredEmployees", AutoIncrementKeys = false, KeyPath = "Id")]
[Index(Name = "FirstName", Path = "firstName")]
public IndexedDbObjectStore Employees { get; }
public TheSpaghettiFactoryDb(IJSRuntime jsRuntime): base(jsRuntime)
{
Version = 1;
}
}
}
For Blazor WebAssembly, in program.cs
public class Program
{
public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
// RWM: You can add this as a Singleton because a WebAssembly app runs in the browser and only has one "user".
builder.Services.AddSingleton<TheSpaghettiFactoryDb>();
await builder.Build().RunAsync();
}
}
For Blazor Web, in startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddSingleton<WeatherForecastService>();
// RWM: Here the database is scoped because each user has their own session.
services.AddScoped<TheSpaghettiFactoryDb>();
}
For the following examples we are going to assume that we have Person class which is defined as follows:
public class Person
{
public long? Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
Mote that you DO NOT have to decorate your objects with any attributes. As IndexedDb is a NoSQL database, it is schema-less, so your object will be serialized and deserialized using the default JSON serializer.
You can also mix types in the same ObjectStore (table), but be careful is you use numbers for keys or objects may collide.
To use IndexedDB in a component or page, first inject the IndexedDbDatabase instance, in this case the TheSpaghettifactoryDb class.
@inject TheSpaghettiFactoryDb database
This will create the database if it not exists and will upgrade schema to new version if it is older.
NOTE: Query calls will do this automatically if the database is not already open.
await database.Open()
var people = await database.Employees.GetAllAsync<Person>();
var person = await database.Employees.GetAsync<long, Person>(id);
var person = await database.Employees.FirstName.GetAsync<string, Person>("John");
var people = await database.Employees.FirstName.GetAllAsync<string, Person>("John");
var newPerson = new Person() {
FirstName = "John",
LastName = "Doe"
};
await database.Employees.AddAsync(newPerson);
await database.Employees.PutAsync<Person>(recordToUpdate)
await database.Employees.DeleteAsync<int>(id)
await database.Employees.ClearAsync()
await database.DeleteDatabaseAsync()
Properties
public string Name
public int Version
public IList<IndexedDBObjectStore> ObjectStores
Constructor
public IndexedDBDatabase(IJSRuntime jsRuntime)
Methods
public async Task OpenAsync();
public async Task DeleteDatabaseAsync();
Properties
public string Name
public string? KeyPath
public bool AutoIncrement
public IList<IndexedDbIndex> Indexes
public IndexedDbDatabase IndexedDbDatabase
Constructors
public IndexedDbObjectStore(IndexedDbDatabase database, ObjectStoreAttribute attribute = null);
public IndexedDbObjectStore(IndexedDbDatabase database, string name, string keyPath = "id", bool autoIncrement = false)
Methods
public async Task AddAsync<TData>(TData data);
public async Task AddAsync<TData, TKey>(TData data, TKey key);
public async Task PutAsync<TData>(TData data);
public async Task PutAsync<TData, TKey>(TData data, TKey key);
public async Task DeleteAsync<TKey>(TKey key);
public async Task ClearStoreAsync();
public async Task BatchAddAsync<TData>(TData[] data);
public async Task BatchPutAsync<TData>(TData[] data);
public async Task BatchDeleteAsync<TKey>(TKey[] key);
public async Task<int> CountAsync();
public async Task<int> CountAsync<TKey>(TKey key);
public async Task<int> CountAsync<TKey>(IDBKeyRange<TKey> key);
public async Task<TResult?> GetAsync<TKey, TResult>(TKey key);
public async Task<List<TResult>> GetAllAsync<TResult>(int? count = null);
public async Task<List<TResult>> GetAllAsync<TKey, TResult>(TKey key, int? count = null);
public async Task<List<TResult>> GetAllAsync<TKey, TResult>(IDBKeyRange<TKey> key, int? count = null);
public async Task<List<TResult>> GetAllAsync<TKey, TResult>(TKey[] key);
public async Task<List<TResult>> GetAllKeysAsync<TResult>(int? count = null);
public async Task<List<TResult>> GetAllKeysAsync<TKey, TResult>(TKey key, int? count = null);
public async Task<List<TResult>> GetAllKeysAsync<TKey, TResult>(IDBKeyRange<TKey> key, int? count = null);
public async Task<List<TResult>> GetAllKeysAsync<TKey, TResult>(TKey[] key);
public async Task<List<TResult>> QueryAsync<TResult>(string filter, int? count = null, int? skip = null);
public async Task<List<TResult>> QueryAsync<TKey, TResult>(string filter, TKey key, int? count = null, int? skip = null);
public async Task<List<TResult>> QueryAsync<TKey, TResult>(string filter, IDBKeyRange<TKey> key, int? count = null, int? skip = null)
Properties
public string Name
public string KeyPath
public bool MultiEntry
public bool Unique
public IndexedDbObjectStore ObjectStore
Constructor
public IndexedDbIndex(IndexedDbObjectStore idbStore, string name, string keyPath, bool multiEntry = false, bool unique = false);
Methods
public async Task<int> CountAsync(string indexName);
public async Task<int> CountAsync<TKey>(TKey key);
public async Task<int> CountAsync<TKey>(IDBKeyRange<TKey> key);
public async Task<TResult> GetAsync<TKey, TResult>(TKey queryValue);
public async Task<List<TResult>> GetAllAsync<TResult>(int? count = null);
public async Task<List<TResult>> GetAllAsync<TKey, TResult>(TKey key, int? count = null);
public async Task<List<TResult>> GetAllAsync<TKey, TResult>(IDBKeyRange<TKey> key, int? count = null);
public async Task<List<TResult>> GetAllAsync<TKey, TResult>(TKey[] key);
public async Task<TResult> GetKeyAsync<TKey, TResult>(TKey queryValue);
public async Task<List<TResult>> GetAllKeysAsync<TResult>(int? count = null);
public async Task<List<TResult>> GetAllKeysAsync<TKey, TResult>(TKey key, int? count = null);
public async Task<List<TResult>> GetAllKeysAsync<TKey, TResult>(IDBKeyRange<TKey> key, int? count = null);
public async Task<List<TResult>> GetAllKeysAsync<TKey, TResult>(TKey[] key);
public async Task<List<TResult>> QueryAsync<TResult>(string filter, int? count = null, int? skip = null);
public async Task<List<TResult>> QueryAsync<TKey, TResult>(string filter, TKey key, int? count = null, int? skip = null);
public async Task<List<TResult>> QueryAsync<TKey, TResult>(string filter, IDBKeyRange<TKey> key, int? count = null, int? skip = null)
The filter expression is the body of a function that receives de parameter obj than handle each record of ObjectStore.
The function must return an Object of type TResult, that will be included in the List<TResult> result and can be one of the following options:
for example, return a list of objects that contains the world "per" in property firstName ordered using index lastName.
List<Person> result = await theFactoryDb.Store("people").Index("lastName").Query<Person>(
"if (obj.firstName.toLowerCase().includes('per')) return obj;"
);
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 net8.0 is compatible. net8.0-android net8.0-android was computed. net8.0-browser net8.0-browser was computed. net8.0-ios net8.0-ios was computed. net8.0-maccatalyst net8.0-maccatalyst was computed. net8.0-macos net8.0-macos was computed. net8.0-tvos net8.0-tvos was computed. net8.0-windows net8.0-windows was computed. net9.0 net9.0 is compatible. net9.0-android net9.0-android was computed. net9.0-browser net9.0-browser was computed. net9.0-ios net9.0-ios was computed. net9.0-maccatalyst net9.0-maccatalyst was computed. net9.0-macos net9.0-macos was computed. net9.0-tvos net9.0-tvos was computed. net9.0-windows net9.0-windows was computed. net10.0 net10.0 is compatible. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
Showing the top 1 NuGet packages that depend on BlazorEssentials.IndexedDb:
| Package | Downloads |
|---|---|
|
SimpleMessageBus.IndexedDb.Core
SimpleMessageBus is a system for making applications more reliable and responsive to users by processing potentially long-running tasks out-of-band from the user's main workflow. It is designed to run either on-prem, or in the Microsoft Cloud, making it suitable for any application, and able to grow as your needs do. |
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 4.0.2 | 557 | 4/6/2026 |
| 4.0.2-preview.3 | 72 | 4/6/2026 |
| 4.0.2-preview.2 | 62 | 4/6/2026 |
| 4.0.2-preview.1 | 91 | 4/6/2026 |
| 4.0.1 | 138 | 4/3/2026 |
| 4.0.0 | 650 | 12/21/2025 |
| 4.0.0-CI-20260324-122351 | 85 | 3/24/2026 |
| 4.0.0-CI-20260323-191045 | 85 | 3/23/2026 |
| 4.0.0-CI-20251220-190326 | 144 | 12/21/2025 |
| 4.0.0-CI-20251123-125950 | 362 | 11/23/2025 |
| 4.0.0-CI-20251116-221555 | 315 | 11/17/2025 |
| 4.0.0-CI-20251115-193536 | 164 | 11/16/2025 |
| 4.0.0-CI-20251115-191703 | 162 | 11/16/2025 |
| 4.0.0-CI-20251112-180912 | 316 | 11/12/2025 |
| 4.0.0-CI-20251112-135817 | 303 | 11/12/2025 |
| 3.0.1-CI-20250120-220559 | 614 | 1/21/2025 |
| 3.0.0 | 3,583 | 11/25/2024 |
| 3.0.0-CI-20250120-213325 | 160 | 1/21/2025 |
| 3.0.0-CI-20241125-003524 | 155 | 11/25/2024 |
| 3.0.0-CI-20241025-225746 | 216 | 10/26/2024 |