Git Product home page Git Product logo

blazordb's Introduction

Forked from https://github.com/Reshiru/Blazor.IndexedDB.Framework as inspiration. A lot has changed since original fork and a lot is planned to get it closer.

BlazorDB

An easy, fast way to use IndexedDB in a Blazor application.

How to Use (WASM)

  • Install dotnet add package BlazorIndexedDB
  • Add .js files to index.html
    <script src="_content/BlazorIndexedDB/dexie.min.js"></script>
    <script src="_content/BlazorIndexedDB/blazorDB.js"></script>
  • Add @using BlazorDB to _Imports.razor
  • Update Program.cs ServiceCollection with new databases (can add as many databases as you want)
    builder.Services.AddBlazorDB(options =>
    {
        options.Name = "Test";
        options.Version = 1;
        options.StoreSchemas = new List<StoreSchema>()
        {
            new StoreSchema()
            {
                Name = "Person",
                PrimaryKey = "id",
                PrimaryKeyAuto = true,
                UniqueIndexes = new List<string> { "name" }
            }
        };
    });
  • Inject IBlazorDbFactory in your Razor pages
    @inject IBlazorDbFactory _dbFactory
  • Start using!
    var manager = await _dbFactory.GetDbManager(dbName)
    await manager.AddRecord(new StoreRecord<object>()
    {
        StoreName = storeName,
        Record = new { Name = "MyName", Age = 20 }
    });

How it works

You defined your databases and store schemes in the ServicesCollection. We add a helper called AddBlazorDB where you can build DbStore. From there, we ensure that an instance of IBlazorDbFactory is available in your service provider and will automatically add all DbStores and IndexedDbManagers based on what is defined with AddBlazorDb. This allows you to have multiple databases if needed.

To access any database/store, all you need to do is inject the IBlazorDbFactory in your page and call GetDbManager(string dbName). We will pull your IndexedDbManager from the factory and make sure it's created and ready.

Most calls will either be true Async or let you pass an Action in. If it lets you pass in an Action, it is optional. This Action will get called when the method is complete. This way, it isn't blocking on WASMs single thread. All of these calls return a Guid which is the "transaction" identifier to IndexeDB (it's not a true database transaction, just the call between C# and javascript that gets tracked).

If the call is flagged as Async, we will wait for the JS callback that it is complete and then return the data. The library takes care of this connection between javascript and C# for you.

Available Calls

  • Task<Guid> OpenDb(Action<BlazorDbEvent> action) - Open the IndexedDb and make sure it is created, with an optional callback when complete
  • Task<Guid> DeleteDb(string dbName, Action<BlazorDbEvent> action) - Delete the database, with an optional callback when complete
  • Task<BlazorDbEvent> DeleteDbAsync(string dbName) - Delete the database and wait for it to complete
  • Task<Guid> AddRecord<T>(StoreRecord<T> recordToAdd, Action<BlazorDbEvent> action) - Add a record to the store, with an optional callback when complete
  • Task<BlazorDbEvent> AddRecordAsync<T>(StoreRecord<T> recordToAdd) - Add a record to the store and wait for it to complete
  • Task<Guid> BulkAddRecord<T>(string storeName, IEnumerable<T> recordsToBulkAdd, Action<BlazorDbEvent> action) - Adds records/objects to the specified store in bulk
  • Task<BlazorDbEvent> BulkAddRecordAsync<T>(string storeName, IEnumerable<T> recordsToBulkAdd) - Adds records/objects to the specified store in bulk and waits for it to complete
  • Task<Guid> UpdateRecord<T>(UpdateRecord<T> recordToUpdate, Action<BlazorDbEvent> action) - Update a record in the store, with an optional callback when c complete
  • Task<BlazorDbEvent> UpdateRecordAsync(UpdateRecord<T> recordToUpdate) - Update a record in the store and wait for it to complete
  • Task<TResult> GetRecordByIdAsync<TInput, TResult>(string storeName, TInput key) - Get a record by the 'id' and wait for it to return
  • Task<Guid> DeleteRecord<TInput>(string storeName, TInput key, Action<BlazorDbEvent> action) - Delete a record in the store by 'id', with an optional callback when complete
  • Task<BlazorDbEvent> DeleteRecordAsync<TInput>(string storeName, TInput key) - Delete a record in the store by 'id' and wait for it to complete
  • Task<BlazorDbEvent> ClearTable<TInput>(string storeName, Action<BlazorDbEvent> action) - Clears all data from a Table but keeps the table
  • Task<BlazorDbEvent> ClearTableAsync<TInput>(string storeName) - Clears all data from a Table but keeps the table and wait for it to complete

More to Come

  • Real queries
  • Automated testing
  • Dynamically add/remove from IBlazorDbFactory

blazordb's People

Contributors

dharmaturtle avatar etaxi341 avatar nwestfall avatar syabiku avatar tjohnston-softdev avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

blazordb's Issues

Documentation out of date?

Hi,

is the documentation out of date?

 builder.Services.AddBlazorDB(options =>
            {
                options.Name = "Test";
                options.Version = 1;

The options only have Debug and an Assembly property.

[Question] Migrate Data on Version Upgrade

Simply changing the version number and updating some values seems to work well. For example, incrementing the version number and adding Indexes to the store schema seems to have added them without any data loss.

But how to you add a more complex migration?

For instance, here is the example from the dexie docs:

db.version(1).stores({
    friends: 'id, name, age'
});
db.version(2).stores({
    friends: 'id, name, firstName, lastName',
}).upgrade(tx => {
    return tx.table("friends").toCollection().modify(friend => {
        const names = friend.name.split(' ');
        friend.firstName = names.shift();
        friend.lastName = names.join(' ');
        delete friend.name;
    });
});

How would you replicate this using this BlazorDB library?

version.upgrade()

I would recommend you add code to fire an event when version.upgrade() fires. That allows you to make manual schema changes or modify data when the version number changes.

Feature Request: read all records in the store

Thank you for your great library.

Would it be possible to have a method for getting all records of a store?
getting records one by one with GetRecordByIdAsync is time-consuming for big stores.

Thanks.

Issue when key is not generated automatically

Hi there

i have a issue when i do not want the primarykey is not autogenerated.
in my case i wanted to be the key as a string.

so i implemented this:
Program.cs
builder.Services.AddBlazorDB(options => { options.Name = "ImageDB"; options.Version = 1; options.StoreSchemas = new List<StoreSchema>() { new StoreSchema { Name = "Image", PrimaryKey = "Id", PrimaryKeyAuto = false, Indexes = new List<string> { "Id", "Content" } } }; });

Model:
public class Image { [Key] public string Id { get; set; } public byte[] Content { get; set; } }

Insert Method:
storeName is filled with its correct store
Entity contains a model you can see above like
Id= "abc.png"
Content = anycontentbytearray

` public async Task<List> InsertAllAsync(List EntityList)
{
await EnsureManager();
try
{
foreach (var Entity in EntityList)
{
try
{
var record = new StoreRecord()
{
StoreName = storeName,
Record = Entity
};
await manager.AddRecordAsync(record);
var allItems = await GetAllAsync();
return allItems;

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);

            }
        }
    }

`

and the error i get is the following:

Unhandled rejection: DataError: Failed to execute 'add' on 'IDBObjectStore': Evaluating the object store's key path did not yield a value. DataError: Failed to execute 'add' on 'IDBObjectStore': Evaluating the object store's key path did not yield a value. Error: Failed to execute 'add' on 'IDBObjectStore': Evaluating the object store's key path did not yield a value.

the issue isnt there when its autogenerated and the id Field is a long.

Could you give me some advice how to fix this issue??

Best Regards

dynamic dbStore and schema

Hi @nwestfall, very useful repo. Do you already have a plan sketched out for dynamic stores and schema? If not, I've started to implement one, while adhering as much as possible to your current approach. I can send a draft pull request if you'd consider it.

PrimaryKey missing

I get this issue when using this new library:

Failed to execute 'add' on 'IDBObjectStore': Evaluating the object store's key path did not yield a value.

looking at the db created from:

new() {
    Name = nameof(StoredFile),
    PrimaryKey = nameof(StoredFile.FileId),
    Indexes = new()
    {
	nameof(StoredFile.DiscussionId),
	nameof(StoredFile.Base64Data)
    }
}

immagine
but as you can see, no FileId is present in the table in an explicit way, only when clicking on the table name I get the key name, but that's it. Do you see what the issue could be?

Fetch whole DB

Hi,
Thanks for the great lib
I have a question. One thing that was bizarre in the original library, it fetched the total IndexedDB into memory and query from that. Do you follow the same pattern or it is implemented another way?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.