1 line
15 KiB
JSON
1 line
15 KiB
JSON
{"path":"NexusReader.Data/Persistence/DbInitializer.cs","purpose":"Database seeder that runs at application startup to ensure initial data (subscription plans, roles, admin user, sample author and ebook) exist in the AppDbContext.","classification":{"role":"bootstrap","layer":"data","confidence":0.92,"evidence":["Class named DbInitializer with a public async SeedAsync(IServiceProvider) method (lines 12-14).","Creates a DI scope and an AppDbContext, writes seed data (SubscriptionPlans, Roles, Users, Authors, Ebooks) and saves via SaveChangesAsync (lines 16-19, 25-36, 38-50, 51-79, 82-107)."]},"className":"DbInitializer","methods":[{"name":"SeedAsync","line":14,"endLine":118,"signature":"(serviceProvider: IServiceProvider) -> Task","purpose":"Create a scoped DbContext and seed initial database data: subscription plans, roles, an admin user (with role), a sample author and an ebook, with logging and error handling.","calls":[{"targetFile":"NexusReader.Domain/Entities/SubscriptionPlan.cs","targetMethod":"FreeId / FreeName / ProId / ProName / EnterpriseId / EnterpriseName (static properties)","callLine":30,"paramSummary":"used to set Id and PlanName when creating SubscriptionPlan instances"},{"targetFile":"NexusReader.Domain/Entities/NexusUser.cs","targetMethod":"NexusUser .ctor (entity creation)","callLine":58,"paramSummary":"instantiates admin NexusUser with email, subscription, tokens, tenant/security stamps"},{"targetFile":"NexusReader.Domain/Entities/Author.cs","targetMethod":"Author .ctor (entity creation)","callLine":86,"paramSummary":"instantiates sample author 'Giorgio Vasari' if missing"},{"targetFile":"NexusReader.Domain/Entities/Ebook.cs","targetMethod":"Ebook .ctor (entity creation)","callLine":94,"paramSummary":"creates sample Ebook for admin user with metadata and file path"}],"actions":[{"id":"resource-acquire_16","kind":"mapping","label":"Create service scope and resolve services","line":16,"detail":"using var scope = serviceProvider.CreateScope(); resolve IPasswordHasher<NexusUser> and IDbContextFactory<AppDbContext> from scope","visibility":"detail-only","confidence":0.7},{"id":"external-call_19","kind":"external-call","label":"Create DbContext async","line":19,"detail":"await dbContextFactory.CreateDbContextAsync() — obtains AppDbContext for persistence operations","visibility":"detail-only","confidence":0.7},{"id":"seedasync_await_19_0","kind":"await","label":"Waits for async work","line":19,"detail":"using var dbContext = await dbContextFactory.CreateDbContextAsync();","visibility":"secondary-visible","confidence":0.81},{"id":"seedasync_try_21_1","kind":"try","label":"Begins protected execution","line":21,"detail":"try","visibility":"primary-visible","confidence":0.84},{"id":"log_23","kind":"log","label":"Starting seeding","line":23,"detail":"Console.WriteLine(\"[Seeder] Starting database seeding...\")","visibility":"detail-only","confidence":0.7},{"id":"seedasync_branch_26_2","kind":"branch","label":"Evaluates branch condition","line":26,"detail":"if (!dbContext.SubscriptionPlans.Any())","conditionSummary":"!dbContext.SubscriptionPlans.Any()","outcomeLabels":["true","false"],"visibility":"secondary-visible","confidence":0.78},{"id":"guard-clause_26","kind":"guard-clause","label":"Seed subscription plans only if none exist","line":26,"detail":"Adds three SubscriptionPlan entities and SaveChangesAsync when no plans exist (lines 28-35)","conditionSummary":"!dbContext.SubscriptionPlans.Any()","outcomeLabels":["add-plans","skip"],"visibility":"detail-only","confidence":0.7},{"id":"persistence-write_28","kind":"mapping","label":"AddRange SubscriptionPlans","line":28,"detail":"dbContext.SubscriptionPlans.AddRange(...); await dbContext.SaveChangesAsync()","visibility":"detail-only","confidence":0.7},{"id":"seedasync_await_34_3","kind":"await","label":"Waits for async work","line":34,"detail":"await dbContext.SaveChangesAsync();","visibility":"secondary-visible","confidence":0.81},{"id":"log_35","kind":"log","label":"Seed progress/info logs","line":35,"detail":"Multiple Console.WriteLine statements after seeding stages (lines 35, 46, 80, 106, 111)","visibility":"detail-only","confidence":0.7},{"id":"seedasync_loop_40_4","kind":"loop","label":"Repeats work over a collection or condition","line":40,"detail":"foreach (var roleName in roleNames)","conditionSummary":"var roleName in roleNames","loopTargetLine":40,"loopExitSummary":"Leaves the loop when the condition no longer holds.","visibility":"primary-visible","confidence":0.86},{"id":"loop_40","kind":"loop","label":"Seed roles (Admin, User)","line":40,"detail":"foreach roleName in roleNames -> checks dbContext.Roles.Any(...) and adds missing IdentityRole entries; then SaveChangesAsync() (lines 40-49, 49)","visibility":"detail-only","confidence":0.7},{"id":"seedasync_branch_43_5","kind":"branch","label":"Evaluates branch condition","line":43,"detail":"if (!roleExist)","conditionSummary":"!roleExist","outcomeLabels":["true","false"],"visibility":"secondary-visible","confidence":0.78},{"id":"seedasync_repository-write_45_6","kind":"repository-write","label":"Writes repository or persistence state","line":45,"detail":"dbContext.Roles.Add(new IdentityRole { Name = roleName, NormalizedName = roleName.ToUpper() });","visibility":"secondary-visible","confidence":0.88},{"id":"seedasync_await_49_7","kind":"await","label":"Waits for async work","line":49,"detail":"await dbContext.SaveChangesAsync();","visibility":"secondary-visible","confidence":0.81},{"id":"persistence-read_54","kind":"mapping","label":"Check for existing admin user","line":54,"detail":"await dbContext.Users.FirstOrDefaultAsync(u => u.NormalizedEmail == normalizedEmail)","visibility":"detail-only","confidence":0.7},{"id":"seedasync_await_54_8","kind":"await","label":"Waits for async work","line":54,"detail":"var adminUser = await dbContext.Users.FirstOrDefaultAsync(u => u.NormalizedEmail == normalizedEmail);","visibility":"secondary-visible","confidence":0.81},{"id":"branch_56","kind":"branch","label":"Admin user existence branch","line":56,"detail":"If missing, create NexusUser, hash password, add to Users, assign Admin role, and seed sample author and ebook (lines 58-107); else log that admin exists (line 111).","conditionSummary":"adminUser == null","outcomeLabels":["create-admin","admin-exists"],"visibility":"detail-only","confidence":0.7},{"id":"seedasync_branch_56_9","kind":"branch","label":"Evaluates branch condition","line":56,"detail":"if (adminUser == null)","conditionSummary":"adminUser == null","outcomeLabels":["true","false"],"visibility":"secondary-visible","confidence":0.78},{"id":"persistence-write_71","kind":"mapping","label":"Create admin user and save","line":71,"detail":"passwordHasher.HashPassword(...); dbContext.Users.Add(adminUser); await dbContext.SaveChangesAsync()","visibility":"detail-only","confidence":0.7},{"id":"seedasync_repository-write_73_10","kind":"repository-write","label":"Writes repository or persistence state","line":73,"detail":"dbContext.Users.Add(adminUser);","visibility":"secondary-visible","confidence":0.88},{"id":"seedasync_await_74_11","kind":"await","label":"Waits for async work","line":74,"detail":"await dbContext.SaveChangesAsync();","visibility":"secondary-visible","confidence":0.81},{"id":"persistence-write_76","kind":"mapping","label":"Assign Admin role to user","line":76,"detail":"fetch role entity and add IdentityUserRole to dbContext.UserRoles; await SaveChangesAsync()","visibility":"detail-only","confidence":0.7},{"id":"seedasync_await_76_12","kind":"await","label":"Waits for async work","line":76,"detail":"var adminRole = await dbContext.Roles.FirstAsync(r => r.Name == \"Admin\");","visibility":"secondary-visible","confidence":0.81},{"id":"seedasync_repository-write_77_13","kind":"repository-write","label":"Writes repository or persistence state","line":77,"detail":"dbContext.UserRoles.Add(new IdentityUserRole<string> { UserId = adminUser.Id, RoleId = adminRole.Id });","visibility":"secondary-visible","confidence":0.88},{"id":"seedasync_await_78_14","kind":"await","label":"Waits for async work","line":78,"detail":"await dbContext.SaveChangesAsync();","visibility":"secondary-visible","confidence":0.81},{"id":"persistence-read-write_83","kind":"mapping","label":"Ensure sample Author exists","line":83,"detail":"await dbContext.Authors.FirstOrDefaultAsync(a => a.Name == \"Giorgio Vasari\"); add if null and SaveChangesAsync","visibility":"detail-only","confidence":0.7},{"id":"seedasync_await_83_15","kind":"await","label":"Waits for async work","line":83,"detail":"var author = await dbContext.Authors.FirstOrDefaultAsync(a => a.Name == \"Giorgio Vasari\");","visibility":"secondary-visible","confidence":0.81},{"id":"seedasync_branch_84_16","kind":"branch","label":"Evaluates branch condition","line":84,"detail":"if (author == null)","conditionSummary":"author == null","outcomeLabels":["true","false"],"visibility":"secondary-visible","confidence":0.78},{"id":"seedasync_repository-write_87_17","kind":"repository-write","label":"Writes repository or persistence state","line":87,"detail":"dbContext.Authors.Add(author);","visibility":"secondary-visible","confidence":0.88},{"id":"seedasync_await_88_18","kind":"await","label":"Waits for async work","line":88,"detail":"await dbContext.SaveChangesAsync();","visibility":"secondary-visible","confidence":0.81},{"id":"persistence-read-write_92","kind":"mapping","label":"Add sample Ebook for admin user","line":92,"detail":"if no ebook exists for adminUser.Id then dbContext.Ebooks.Add(new Ebook{...}); await SaveChangesAsync()","visibility":"detail-only","confidence":0.7},{"id":"seedasync_branch_92_19","kind":"branch","label":"Evaluates branch condition","line":92,"detail":"if (!dbContext.Ebooks.Any(e => e.UserId == adminUser.Id))","conditionSummary":"!dbContext.Ebooks.Any(e => e.UserId == adminUser.Id)","outcomeLabels":["true","false"],"visibility":"secondary-visible","confidence":0.78},{"id":"seedasync_repository-write_94_20","kind":"repository-write","label":"Writes repository or persistence state","line":94,"detail":"dbContext.Ebooks.Add(new Ebook","visibility":"secondary-visible","confidence":0.88},{"id":"seedasync_await_105_21","kind":"await","label":"Waits for async work","line":105,"detail":"await dbContext.SaveChangesAsync();","visibility":"secondary-visible","confidence":0.81},{"id":"seedasync_fallback_109_22","kind":"fallback","label":"Falls back to alternate path","line":109,"detail":"else","outcomeLabels":["fallback"],"visibility":"primary-visible","confidence":0.84},{"id":"seedasync_catch_114_23","kind":"catch","label":"Handles exception path","line":114,"detail":"catch (Exception ex)","conditionSummary":"Exception ex","outcomeLabels":["handled exception"],"visibility":"primary-visible","confidence":0.86},{"id":"error-handling_114","kind":"mapping","label":"Top-level seeding exception catch","line":114,"detail":"catch (Exception ex) { Console.WriteLine('[Seeder] Critical error during seeding: ' + ex.Message); }","visibility":"detail-only","confidence":0.7}]}],"types":[],"serviceRegistrations":[],"startupActions":[{"name":"SeedAsync","line":14,"kind":"unknown","targetCalls":[{"targetFile":"NexusReader.Data/Persistence/AppDbContext.cs","targetMethod":"AppDbContext (persistence operations via created DbContext)","callLine":19,"paramSummary":"uses created AppDbContext to query and save entities"}]}],"dependencies":["NexusReader.Domain/Entities/SubscriptionPlan.cs","NexusReader.Domain/Entities/NexusUser.cs","NexusReader.Domain/Entities/Author.cs","NexusReader.Domain/Entities/Ebook.cs","NexusReader.Data/Persistence/AppDbContext.cs"],"patterns":["Seeder","Data Seeding"],"domainConcepts":["SubscriptionPlan","Role","User (NexusUser)","Author","Ebook"],"keyDetails":"Runs inside a DI scope, creates/uses AppDbContext via IDbContextFactory, performs multiple conditional seeds with SaveChangesAsync calls and top-level exception logging; intended to be executed at app startup to ensure minimal required data exists.","orchestrationMethods":[{"name":"SeedAsync","line":14,"confidence":0.98,"reason":"Coordinates 4 downstream calls with 15 architectural actions.","actionKinds":["mapping","external-call","await","try","log","branch","guard-clause","loop","repository-write","fallback","catch"],"evidencePaths":["NexusReader.Data/Persistence/DbInitializer.cs","NexusReader.Domain/Entities/SubscriptionPlan.cs","NexusReader.Domain/Entities/NexusUser.cs","NexusReader.Domain/Entities/Author.cs","NexusReader.Domain/Entities/Ebook.cs"]}],"typedContracts":[],"persistenceInteractions":[{"methodName":"SeedAsync","line":45,"kind":"persistence-write","detail":"dbContext.Roles.Add(new IdentityRole { Name = roleName, NormalizedName = roleName.ToUpper() });","evidencePaths":["NexusReader.Data/Persistence/DbInitializer.cs"]},{"methodName":"SeedAsync","line":73,"kind":"persistence-write","detail":"dbContext.Users.Add(adminUser);","evidencePaths":["NexusReader.Data/Persistence/DbInitializer.cs"]},{"methodName":"SeedAsync","line":77,"kind":"persistence-write","detail":"dbContext.UserRoles.Add(new IdentityUserRole<string> { UserId = adminUser.Id, RoleId = adminRole.Id });","evidencePaths":["NexusReader.Data/Persistence/DbInitializer.cs"]},{"methodName":"SeedAsync","line":87,"kind":"persistence-write","detail":"dbContext.Authors.Add(author);","evidencePaths":["NexusReader.Data/Persistence/DbInitializer.cs"]},{"methodName":"SeedAsync","line":94,"kind":"persistence-write","detail":"dbContext.Ebooks.Add(new Ebook","evidencePaths":["NexusReader.Data/Persistence/DbInitializer.cs"]}],"externalInteractions":[{"methodName":"SeedAsync","line":19,"kind":"external-call","detail":"await dbContextFactory.CreateDbContextAsync() — obtains AppDbContext for persistence operations","evidencePaths":["NexusReader.Data/Persistence/DbInitializer.cs"]}],"evidenceAnchors":[{"kind":"orchestration-method","label":"SeedAsync","line":14,"summary":"Coordinates 4 downstream calls with 15 architectural actions.","confidence":0.98,"evidencePaths":["NexusReader.Data/Persistence/DbInitializer.cs","NexusReader.Domain/Entities/SubscriptionPlan.cs","NexusReader.Domain/Entities/NexusUser.cs","NexusReader.Domain/Entities/Author.cs","NexusReader.Domain/Entities/Ebook.cs"]},{"kind":"persistence","label":"SeedAsync","line":45,"summary":"dbContext.Roles.Add(new IdentityRole { Name = roleName, NormalizedName = roleName.ToUpper() });","confidence":0.82,"evidencePaths":["NexusReader.Data/Persistence/DbInitializer.cs"]},{"kind":"persistence","label":"SeedAsync","line":73,"summary":"dbContext.Users.Add(adminUser);","confidence":0.82,"evidencePaths":["NexusReader.Data/Persistence/DbInitializer.cs"]},{"kind":"persistence","label":"SeedAsync","line":77,"summary":"dbContext.UserRoles.Add(new IdentityUserRole<string> { UserId = adminUser.Id, RoleId = adminRole.Id });","confidence":0.82,"evidencePaths":["NexusReader.Data/Persistence/DbInitializer.cs"]},{"kind":"external-call","label":"SeedAsync","line":19,"summary":"await dbContextFactory.CreateDbContextAsync() — obtains AppDbContext for persistence operations","confidence":0.8,"evidencePaths":["NexusReader.Data/Persistence/DbInitializer.cs"]},{"kind":"startup","label":"SeedAsync","line":14,"summary":"unknown startup action","confidence":0.78,"evidencePaths":["NexusReader.Data/Persistence/DbInitializer.cs","NexusReader.Data/Persistence/AppDbContext.cs"]}],"cacheMetadata":{"schemaVersion":2,"analysisVersion":"2026-05-23.cache-v1","contentChecksum":"9c24bc671bfedfc3282154c1658412bccee49e792757973409dbca7c6519cd68","sourceByteSize":5464,"analyzedAt":"2026-05-23T16:25:44.144Z","technology":"dotnet"}} |