diff --git a/Magic.IndexedDb/Extensions/ServiceCollectionExtensions.cs b/Magic.IndexedDb/Extensions/ServiceCollectionExtensions.cs index 2c8ef38..9b86b3a 100644 --- a/Magic.IndexedDb/Extensions/ServiceCollectionExtensions.cs +++ b/Magic.IndexedDb/Extensions/ServiceCollectionExtensions.cs @@ -41,7 +41,7 @@ public static IServiceCollection AddMagicBlazorDB(this IServiceCollection servic long jsMessageSizeBytes, bool isDebug) { services.AddScoped(sp => - new MagicDbFactory(sp, sp.GetRequiredService(), jsMessageSizeBytes)); + new MagicDbFactory(sp.GetRequiredService(), jsMessageSizeBytes)); if (isDebug) { diff --git a/Magic.IndexedDb/Factories/MagicDbFactory.cs b/Magic.IndexedDb/Factories/MagicDbFactory.cs index 7f6bc21..c9be20b 100644 --- a/Magic.IndexedDb/Factories/MagicDbFactory.cs +++ b/Magic.IndexedDb/Factories/MagicDbFactory.cs @@ -7,44 +7,60 @@ using System.Collections.Concurrent; using System.Reflection; using Magic.IndexedDb.LinqTranslation.Interfaces; +using System.Diagnostics; +using System.Threading; namespace Magic.IndexedDb.Factories { internal class MagicDbFactory : IMagicIndexedDb, IAsyncDisposable { - internal MagicDbFactory(long jsMessageSizeBytes) + // null value indicates that the factory is disposed + Lazy>? _jsModule; + Lazy> _magicJsManager; + public MagicDbFactory(IJSRuntime jSRuntime, long jsMessageSizeBytes) { - Cache.JsMessageSizeBytes = jsMessageSizeBytes; - } - - Lazy>? _jsRuntime; - readonly IServiceProvider _serviceProvider; - public static IndexedDbManager? _MagicJsManager { get; set; } = null; - private IJSObjectReference? _cachedJsModule; // Shared JS module instance - public MagicDbFactory(IServiceProvider serviceProvider, IJSRuntime jSRuntime, long jsMessageSizeBytes) - { - _serviceProvider = serviceProvider; - this._jsRuntime = new(() => jSRuntime.InvokeAsync( + this._jsModule = new(() => jSRuntime.InvokeAsync( "import", - "./_content/Magic.IndexedDb/magicDbMethods.js").AsTask()); - } + "./_content/Magic.IndexedDb/magicDbMethods.js").AsTask(), + isThreadSafe: true); - /// - /// Get or initialize the shared JavaScript module. - /// - private async Task GetJsModuleAsync() - { - if (_cachedJsModule is not null) - return _cachedJsModule; + this._magicJsManager = new(async () => + { + var jsModule = await this._jsModule.Value; + + var dbSchemas = SchemaHelper.GetAllSchemas(); + // Create & Open the database (formerly in IndexedDbManager) + var manager = new IndexedDbManager(jsModule); - _cachedJsModule = await _jsRuntime.Value; - return _cachedJsModule; + var dbSets = SchemaHelper.GetAllIndexedDbSets(); + + if (dbSets != null) + { + foreach (var dbSet in dbSets) + { + await new MagicJsInvoke(jsModule).CallJsAsync(Cache.MagicDbJsImportPath, + IndexedDbFunctions.CREATE_LEGACY, default, + new TypedArgument(new DbStore() + { + Name = dbSet.DatabaseName, + Version = 1, + StoreSchemas = dbSchemas + })); + } + } + else + { + Console.WriteLine("No IndexedDbSet found and/or no found IMagicRepository."); + } + return manager; + }, + isThreadSafe: true); } public async ValueTask DisposeAsync() { - var js = _jsRuntime; - _jsRuntime = null; + var js = _jsModule; + _jsModule = null; if (js is null || !js.IsValueCreated) return; @@ -79,58 +95,23 @@ public async ValueTask DisposeAsync() } } - /// - /// Ensure a database is opened and properly associated with the shared JS module. - /// - private async ValueTask GetOrCreateDatabaseAsync(CancellationToken cancellationToken = default) - { - if (_MagicJsManager != null) - return _MagicJsManager; // Return cached instance - - var jsModule = await GetJsModuleAsync(); // Ensure shared JS module is ready - - var dbSchemas = SchemaHelper.GetAllSchemas(); - // Create & Open the database (formerly in IndexedDbManager) - var manager = new IndexedDbManager(jsModule); - - var dbSets = SchemaHelper.GetAllIndexedDbSets(); - - if (dbSets != null) - { - foreach (var dbSet in dbSets) - { - await new MagicJsInvoke(jsModule).CallJsAsync(Cache.MagicDbJsImportPath, - IndexedDbFunctions.CREATE_LEGACY, cancellationToken, - new TypedArgument(new DbStore() - { - Name = dbSet.DatabaseName, - Version = 1, - StoreSchemas = dbSchemas - })); - } - } - else - { - Console.WriteLine("No IndexedDbSet found and/or no found IMagicRepository."); - } - _MagicJsManager = manager; // Cache the opened database - return _MagicJsManager; - } - - /// /// Get storage estimate using the shared JS module. /// public async Task GetStorageEstimateAsync(CancellationToken cancellationToken = default) { - var jsModule = await GetJsModuleAsync(); // Shared JS module reference + ObjectDisposedException.ThrowIf(this._jsModule is null, this); + + var jsModule = await this._jsModule.Value; var magicUtility = new MagicUtilities(jsModule); return await magicUtility.GetStorageEstimateAsync(); } [Obsolete("Not fully implemented yet until full migration protocol finished.")] public async ValueTask> Query(IndexedDbSet indexedDbSet) - where T : class, IMagicTableBase, new() + where T : class, IMagicTableBase, new() { + ObjectDisposedException.ThrowIf(this._jsModule is null, this); + // Get database name and schema name string databaseName = indexedDbSet.DatabaseName; string schemaName = SchemaHelper.GetTableName(); @@ -140,9 +121,11 @@ public async ValueTask> Query(IndexedDbSet indexedDbSet) public async ValueTask> Query( - Func dbSetSelector) - where T : class, IMagicTableBase, new() + Func dbSetSelector) + where T : class, IMagicTableBase, new() { + ObjectDisposedException.ThrowIf(this._jsModule is null, this); + // Create an instance of T to access `DbSets` var modelInstance = new T(); @@ -153,7 +136,9 @@ public async ValueTask> Query( string databaseName = selectedDbSet.DatabaseName; string schemaName = SchemaHelper.GetTableName(); +#pragma warning disable CS0618 return await QueryOverride(databaseName, schemaName); +#pragma warning restore CS0618 } /// @@ -161,31 +146,33 @@ public async ValueTask> Query( /// public async ValueTask> Query() where T : class, IMagicTableBase, new() - { + { + ObjectDisposedException.ThrowIf(this._jsModule is null, this); + string databaseName = SchemaHelper.GetDefaultDatabaseName(); string schemaName = SchemaHelper.GetTableName(); - var dbManager = await GetOrCreateDatabaseAsync(); + var dbManager = await this._magicJsManager.Value; +#pragma warning disable CS0618 return await QueryOverride(databaseName, schemaName); +#pragma warning restore CS0618 } [Obsolete("Not decided if this will be built in further or removed")] public async ValueTask> QueryOverride(string databaseNameOverride, string schemaNameOverride) where T: class, IMagicTableBase, new () { - var dbManager = await GetOrCreateDatabaseAsync(); // Ensure database is open + ObjectDisposedException.ThrowIf(this._jsModule is null, this); + + var dbManager = await this._magicJsManager.Value; return dbManager.Query(databaseNameOverride, schemaNameOverride); } public async ValueTask Database(IndexedDbSet indexedDbSet) { - var dbManager = await GetOrCreateDatabaseAsync(); // Ensure database is open + ObjectDisposedException.ThrowIf(this._jsModule is null, this); + + var dbManager = await this._magicJsManager.Value; return dbManager.Database(dbManager, indexedDbSet); } - - //public async ValueTask Database() - //{ - // throw new Exception("Still working on it."); - //} - } } \ No newline at end of file diff --git a/TestServer/TestServer/Components/Pages/Home.razor b/TestServer/TestServer/Components/Pages/Home.razor index 0a1aebf..1b74460 100644 --- a/TestServer/TestServer/Components/Pages/Home.razor +++ b/TestServer/TestServer/Components/Pages/Home.razor @@ -158,9 +158,6 @@ { if (firstRender) { - try - { - // Targets the default database automatically if called without any parameters. IMagicQuery personQuery = await _MagicDb.Query(); await personQuery.ClearTable(); @@ -758,11 +755,6 @@ StateHasChanged(); - } - catch (Exception ex) - { - Console.WriteLine(ex.Message); - } } } } \ No newline at end of file diff --git a/TestServer/TestServer/appsettings.Development.json b/TestServer/TestServer/appsettings.Development.json index 0c208ae..5057641 100644 --- a/TestServer/TestServer/appsettings.Development.json +++ b/TestServer/TestServer/appsettings.Development.json @@ -1,8 +1,11 @@ { - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - } + "Logging": + { + "LogLevel": + { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "DetailedErrors": true }