You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
ClearTables() was declared as async void, meaning LoadSeedDataAsync() could not await it. This created a race condition where seed data inserts could execute before table drops completed. Any exception inside async void would also crash the app silently (unhandled on the thread pool), and the original error was swallowed via Console.WriteLine.
SeedDataService.ClearTables() called Task.WhenAll on all four repositories concurrently. However, ProjectRepository.DropTableAsync() internally already calls _taskRepository.DropTableAsync() and _tagRepository.DropTableAsync(). This caused the same tables to be dropped from two concurrent call sites simultaneously, risking SQLite locking errors (SQLITE_BUSY) and non-deterministic behavior.
The file was named TaskRespository.cs (note "Resp" instead of "Repo") while the class inside was correctly named TaskRepository. This typo made the file hard to discover and inconsistent with the rest of the codebase.
All four repositories used a simple bool _hasBeenInitialized flag to guard Init(). Under concurrent async access, multiple callers could pass the if (_hasBeenInitialized) return; check before any of them set the flag to true, resulting in multiple table creation attempts running in parallel.
ListAsync() issued separate SQL queries for each project's tags and tasks. With N projects this results in 2N+1 total queries, which is inefficient and a well-known anti-pattern.
The ProjectsTags class was defined but never referenced anywhere in the codebase. The join table is managed entirely via raw SQL in TagRepository. The class also had an ID field not present in the actual database schema (which uses a composite primary key).
In ListAsync(int projectID), one SQL parameter was added without the @ prefix:
MainPageModel: returned null when project was null → caller receives a null Task, which can throw NullReferenceException if awaited.
JsonContext was the only class in the entire template with no namespace declaration, making it a global-namespace type. This was inconsistent and could cause resolution ambiguity.
DisplaySnackbarAsync created a CancellationTokenSource that was never disposed and had no timeout, meaning it would hold resources indefinitely.
Problems
ClearTables()was declared asasync void, meaningLoadSeedDataAsync()could notawaitit. This created a race condition where seed data inserts could execute before table drops completed. Any exception insideasync voidwould also crash the app silently (unhandled on the thread pool), and the original error was swallowed viaConsole.WriteLine.SeedDataService.ClearTables()calledTask.WhenAllon all four repositories concurrently. However,ProjectRepository.DropTableAsync()internally already calls_taskRepository.DropTableAsync()and_tagRepository.DropTableAsync(). This caused the same tables to be dropped from two concurrent call sites simultaneously, risking SQLite locking errors (SQLITE_BUSY) and non-deterministic behavior.TaskRespository.cs(note "Resp" instead of "Repo") while the class inside was correctly namedTaskRepository. This typo made the file hard to discover and inconsistent with the rest of the codebase.bool _hasBeenInitializedflag to guardInit(). Under concurrentasyncaccess, multiple callers could pass theif (_hasBeenInitialized) return;check before any of them set the flag totrue, resulting in multiple table creation attempts running in parallel.ListAsync()issued separate SQL queries for each project's tags and tasks. With N projects this results in 2N+1 total queries, which is inefficient and a well-known anti-pattern.ProjectsTagsclass was defined but never referenced anywhere in the codebase. The join table is managed entirely via raw SQL inTagRepository. The class also had anIDfield not present in the actual database schema (which uses a composite primary key).ListAsync(int projectID), one SQL parameter was added without the@prefix:MainPageModel: returnednullwhen project was null → caller receives a nullTask, which can throwNullReferenceExceptionif awaited.JsonContextwas the only class in the entire template with nonamespacedeclaration, making it a global-namespace type. This was inconsistent and could cause resolution ambiguity.DisplaySnackbarAsynccreated aCancellationTokenSourcethat was never disposed and had no timeout, meaning it would hold resources indefinitely.Steps to Reproduce