master - .Net5 version
master_net31 - 3.x version
DnetIndexedDb
This is a Blazor library to work with IndexedDB DOM API. It allows query multiple IndexedDb databases simultaneously
The actual API expose the following methods:
- Open and upgrade an instance of IndexedDB
- Close an instance of IndexedDB
- Delete an instance of IndexedDB
- Add an item to a given store
- Update an item in a given store
- Delete an item from a store by key
- Delete all items from a store
- Retrieve all items from a given store
- Retrieve an items by index
- Retrieve a range of items by key
- Retrieve a range of items by index
Compatibility *Server-side Blazor and client-side Blazor
Using the library
- Install the Nuget package DnetIndexedDb
- Add the following script reference to your Index.html after the blazor.webassembly.js reference:
<script src="_content/DnetIndexedDb/rxjs.min.js"></script><script src="_content/DnetIndexedDb/dnet-indexeddb.js"></script> - create a new instance of
IndexedDbDatabaseModel - Create a derive class from
IndexedDbInterop
public class GridColumnDataIndexedDb : IndexedDbInterop
{
public GridColumnDataIndexedDb(IJSRuntime jsRuntime, IndexedDbOptions<GridColumnDataIndexedDb> options)
:base(jsRuntime, options)
{
}
}- Register your derive class in
ConfiguredServicesonStartup.cs. When register use options to add the IndexedDbDatabaseModel instance.
services.AddIndexedDbDatabase<GridColumnDataIndexedDb>(options =>
{
options.UseDatabase(GetGridColumnDatabaseModel());
});- Inject the created instance of your derived class into the component or page.
Detailed configuration and use
Step 1 - Create the database model
To create the database model use the following classes. You can find more info about the IndexedDB database here: https://www.w3.org/TR/IndexedDB-2/#database-construct
IndexedDbDatabase
IndexedDbDatabaseModel
IndexedDbIndex
IndexedDbStore
IndexedDbStoreParameter
See the example below
public class IndexedDbDatabaseModel
{
public string Name { get; set; }
public int Version { get; set; }
public List<IndexedDbStore> Stores { get; set; } = new List<IndexedDbStore>();
public int DbModelId { get; set; }
} var indexedDbDatabaseModel = new IndexedDbDatabaseModel
{
Name = "GridColumnData",
Version = 1,
Stores = new List<IndexedDbStore>
{
new IndexedDbStore
{
Name = "tableField",
Key = new IndexedDbStoreParameter
{
KeyPath = "tableFieldId",
AutoIncrement = true
},
Indexes = new List<IndexedDbIndex>
{
new IndexedDbIndex
{
Name = "tableFieldId",
Definition = new IndexedDbIndexParameter
{
Unique = true
}
},
new IndexedDbIndex
{
Name = "attachedProperty",
Definition = new IndexedDbIndexParameter
{
Unique = false
}
},
new IndexedDbIndex
{
Name = "fieldVisualName",
Definition = new IndexedDbIndexParameter
{
Unique = false
}
}, new IndexedDbIndex
{
Name = "hide",
Definition = new IndexedDbIndexParameter
{
Unique = false
}
},
new IndexedDbIndex
{
Name = "isLink",
Definition = new IndexedDbIndexParameter
{
Unique = false
}
},
new IndexedDbIndex
{
Name = "memberOf",
Definition = new IndexedDbIndexParameter
{
Unique = false
}
},
new IndexedDbIndex
{
Name = "tableName",
Definition = new IndexedDbIndexParameter
{
Unique = false
}
},
new IndexedDbIndex
{
Name = "textAlignClass",
Definition = new IndexedDbIndexParameter
{
Unique = false
}
},
new IndexedDbIndex
{
Name = "type",
Definition = new IndexedDbIndexParameter
{
Unique = false
}
},
new IndexedDbIndex
{
Name = "width",
Definition = new IndexedDbIndexParameter
{
Unique = false
}
}
}
}
},
DbModelId = 0
};Create database model by @Kylar182
public class TableFieldDatabase : IndexedDbDatabaseModel
{
public TableFieldDatabase()
{
Name = "GridColumnData";
Version = 1;
Stores = _stores;
}
/// <summary>
/// List of Object Stores
/// </summary>
private List<IndexedDbStore> _stores => new List<IndexedDbStore>
{
_tableFieldStore,
};
private IndexedDbStore _tableFieldStore => new TStore<TableFieldDto>();
}
public class TStore<T> : IndexedDbStore where T : class
{
private IndexedDbStoreParameter _key;
private readonly List<IndexedDbIndex> _indexes = new List<IndexedDbIndex>();
public TStore()
{
BuildStore();
Name = typeof(T).Name.ToPlural();
Key = _key;
Indexes = _indexes;
}
private void BuildStore()
{
foreach (PropertyInfo info in typeof(T).GetProperties())
{
var classId = info.Name.Substring(info.Name.Length - 2);
var classAttrs = info.GetCustomAttributes(true);
var keyAttr = classAttrs.Select(p => p as KeyAttribute).FirstOrDefault();
if (classId == "Id" || keyAttr != null)
{
_key = new IndexedDbStoreParameter
{
KeyPath = info.Name.ToCamelCase(),
AutoIncrement = true
};
}
_indexes.Add(new IndexedDbIndex
{
Name = info.Name.ToCamelCase(),
Definition = new IndexedDbIndexParameter { Unique = false }
});
}
}
}Step 2 - Creating a service
You can create a service for any indexedDB's database that you want to use in your application. Use the base class IndexedDbInterop to create your derived class. See code below.
public class GridColumnDataIndexedDb : IndexedDbInterop
{
public GridColumnDataIndexedDb(IJSRuntime jsRuntime, IndexedDbOptions<GridColumnDataIndexedDb> options)
:base(jsRuntime, options)
{
}
}This follows a similar pattern to what you do when you create a new DbContext in EF core.
Step 3 - Registering a service
You can use the AddIndexedDbDatabase extension method to register your service in ConfiguredServices on Startup.cs. Use the options builder to add the service Database. See code below.
services.AddIndexedDbDatabase<GridColumnDataIndexedDb>(options =>
{
options.UseDatabase(GetGridColumnDatabaseModel());
});GetGridColumnDatabaseModel() return an instance of IndexedDbDatabaseModel
You can also use multiple database, declaring as many service as you want.
services.AddIndexedDbDatabase<SecuritySuiteDataIndexedDb>(options =>
{
options.UseDatabase(GetSecurityDatabaseModel());
});Using the service in your application
To use IndexedDB service in a component or page first inject the IndexedDB servicer instance.
@inject GridColumnDataIndexedDb GridColumnDataIndexedDbIndexedDB store are the equivalent of table in SQL Database. For the API demostrations will use the following class as our store model.
public class TableFieldDto
{
public int TableFieldId { get; set; }
public string TableName { get; set; }
public string FieldVisualName { get; set; }
public string AttachedProperty { get; set; }
public bool IsLink { get; set; }
public int MemberOf { get; set; }
public int Width { get; set; }
public string TextAlignClass { get; set; }
public bool Hide { get; set; }
public string Type { get; set; }
}API examples
Open and upgrade an instance of IndexedDB
ValueTask<int> OpenIndexedDb()
var result = await GridColumnDataIndexedDb.OpenIndexedDb();Add an items to a given store
ValueTask<TEntity> AddItems<TEntity>(string objectStoreName, List<TEntity> items)
var result = await GridColumnDataIndexedDb.AddItems<TableFieldDto>("tableField", items);Retrieve an item by key
ValueTask<TEntity> GetByKey<TKey, TEntity>(string objectStoreName, TKey key)
var result = await GridColumnDataIndexedDb.GetByKey<int, TableFieldDto>("tableField", 11);Delete an item from a store by key
ValueTask<string> DeleteByKey<TKey>(string objectStoreName, TKey key)
var result = await GridColumnDataIndexedDb.DeleteByKey<int>("tableField", 11);Retrieve all items from a given store
ValueTask<List<TEntity>> GetAll<TEntity>(string objectStoreName)
var result = await GridColumnDataIndexedDb.GetAll<TableFieldDto>("tableField");Retrieve a range of items by key
ValueTask<List<TEntity>> GetRange<TKey, TEntity>(string objectStoreName, TKey lowerBound, TKey upperBound)
var result = await GridColumnDataIndexedDb.GetRange<int, TableFieldDto>("tableField", 15, 20);Retrieve a range of items by index
ValueTask<List<TEntity>> GetByIndex<TKey, TEntity>(string objectStoreName, TKey lowerBound, TKey upperBound, string dbIndex, bool isRange)
var result = await GridColumnDataIndexedDb.GetByIndex<string, TableFieldDto>("tableField", "Name", null, "fieldVisualName", false);Update items in a given store
ValueTask<string> UpdateItems<TEntity>(string objectStoreName, List<TEntity> items)
foreach (var item in items)
{
item.FieldVisualName = item.FieldVisualName + "Updated";
}
var result = await GridColumnDataIndexedDb.UpdateItems<TableFieldDto>("tableField", items);Delete all items from a store
ValueTask<string> DeleteAll(string objectStoreName)
var result = await GridColumnDataIndexedDb.DeleteAll("tableField");Delete an instance of IndexedDB
ValueTask<string> DeleteIndexedDb()
var result = await GridColumnDataIndexedDb.DeleteIndexedDb();