Trying to create a MAUI App using SQLLite database service, and for the Database service to be used by both UI pages and WorkManager background workers. I have registered the Database service as a Singleton DI Service but when the WorkManager Workers and / or UI pages ( main thread ) construct themselves when needing the Database Service , the DI Context seems to be different and it creates 2 Database services. I was hoping it could be shared meaning one Singleton Database service for the whole app as to control better the single SQLLite writer limitation.
Not sure how else to let UI and background workers use the database service without running into concurrency or database corruption issues due to both trying to write data at the same time.
I tried various MauiProgram.cs DI Service registration variations and change of timings regarding using a CustomWorkManager and either initializing it in the MainApplication.cs or outside the Mauiprogram.cs as part of this code .
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder.Services.AddSingleton<Services.IDatabaseService,Services.DatabaseService>();
#if ANDROID
builder.Services.AddSingleton<CustomWorkManagerFactory>();
builder.Services.AddSingleton<Platforms.Android.Sync.SyncWorker>();
#endif
var app = builder.Build();
Helpers.ServiceLocator.ServiceProvider = builder.Services.BuildServiceProvider();
#if ANDROID
var context = Android.App.Application.Context;
var customFactory = Helpers.ServiceLocator.ServiceProvider.GetRequiredService<Platforms.Android.Helpers.CustomWorkManagerFactory>();
var configuration = new AndroidX.Work.Configuration.Builder()
.SetWorkerFactory(customFactory)
.Build();
AndroidX.Work.WorkManager.Initialize(context, configuration);
#endif
return app;
Also inside the Database Service the write logic is protected by Semaphoreslims eg
public async Task<int> InsertDB(object item) {
await _writeSemaphore.WaitAsync(); try { int result = await Database().InsertAsync(item); return result; } catch (Exception ex) { throw; } finally { _writeSemaphore.Release(); } }
But whatever I try, it seems to construct a new DatabaseService when a worker is created or when UI kicks off the show pages. It never finds / re uses the Singleton Database Service created by the 1st process that instantiated it. Perhaps its impossible as they run in different memory spaces etc.
Can it be done? if so looking forward receiving suggestions.
Ultimately its about keeping the single SQLLite writer in check across the whole app but like I said I thought having a DI Singleton Service together with the SemaphoreSlim would do the trick. Accurate / independent database activity across all parts of the app is the main requirement to get right.
Thank you for any suggestions.
Not sure how else to let UI and background workers use the database service without running into concurrency or database corruption issues due to both trying to write data at the same time.How does having a singleton stop this? Am I missing something? You need to use alockto avoid this as far as I know and if you are using SqliteAsync then you need to useSemaphoreSlim