Main Goal
I am creating a Blazor app that will display a single paragraph of a report one at a time. The user will need to click on some button to go to the next paragraph of the report. I need to create a database with tables for paragraphs, section headers, and documents.
My question
My question is related to the database part and the way on how to read the data from the database. I have used EntityFramework and SQLite to create a database. I want to know if I have done it correctly or not.
For this example, I have created sample data of paragraphs and sections. The relationship of each paragraph to a section is collected in a separate table named SectionParagraphs. (The relationship case for Documents and sections is similar, and I have thus not included them in this example).
I have sketched a simple model in the figure below. So, basically, a document will consist of sections, and each section will consist of Paragraphs.
I have included the codes below. Do you think this is good method? and what will happen if there are millions of paragraphs. I am worried that this code will be slow.
CodeTo make things simple, I am only going to show the latter three classes.
Here is Section.cs class.
public class Section{ [Key] public int Id { get; set; } public string Name { get; set; }}Here is Paragraph.cs class.
public class Paragraph{ [Key] public int Id { get; set; } public string Name { get; set; }}Here is relationship class SectionParagraph.cs class.
public class SectionParagraph{ public int ParagraphId { get; set; } public int SectionId { get; set; }}and, heere is DbContext class.
public class ReportContext : DbContext{ public DbSet<Paragraph> Paragraphs { get; set; } public DbSet<Section> Sections { get; set; } public DbSet<SectionParagraph> SectionParagraphs { get; set; } public ReportContext(DbContextOptions<ReportContext> options) : base(options) { } protected override void OnModelCreating(ModelBuilder mb) { mb.Entity<SectionParagraph>().HasKey(s=> new { s.SectionId, s.ParagraphId }); mb.Entity<SectionParagraph>().HasOne<Section>().WithMany(e=> e.SectionParagraphs); }}Here is seedData.cs class.
public class SeedData{ public static void InitializeChecklist(ReportContext db) { List<Section> sections = new List<Section>(); for(int i = 1; i < 11; i++) { sections.Add(new Section() { Id = i, Name = String.Format("Section {0}", i) }); } List<Paragraph> paragraphs = new List<Paragraph>(); for (int i = 1; i < 21; i++) { paragraphs.Add(new Paragraph() { Id = i, Name = String.Format("Paragraph No. {0}", i) }); } SectionParagraph[] sectionParagraphs = new SectionParagraph[] { new SectionParagraph(){ SectionId = 1, ParagraphId = 1 }, new SectionParagraph(){ SectionId = 2, ParagraphId = 2 }, new SectionParagraph(){ SectionId = 3, ParagraphId = 3 }, new SectionParagraph(){ SectionId = 4, ParagraphId = 4 }, new SectionParagraph(){ SectionId = 4, ParagraphId = 5 }, new SectionParagraph(){ SectionId = 4, ParagraphId = 6 }, new SectionParagraph(){ SectionId = 4, ParagraphId = 7 }, new SectionParagraph(){ SectionId = 4, ParagraphId = 8 }, new SectionParagraph(){ SectionId = 4, ParagraphId = 9 } } db.SectionParagraphs.AddRange(sectionParagraphs); db.Sections.AddRange(sections); db.Paragraphs.AddRange(paragraphs); db.SaveChanges(); }}and, here is the Index.razor
@page "/"@using SampleBlazorApp.Model;@inject HttpClient HttpClient;@inject NavigationManager NavigationManager<PageTitle>Index</PageTitle>@if (paragraphs is null){<p>Loading....</p>}else{ if (_currentIndex < sectionParagraphs.Count) {<p><b>Section Id: @sections.Where(s => s.Id == sectionParagraph.SectionId).FirstOrDefault().Id</b></p><p><b>Section Name: @sections.Where(s => s.Id == sectionParagraph.SectionId).FirstOrDefault().Name</b></p><p>ParagraphNumber: @paragraphs.Where(s => s.Id == sectionParagraph.ParagraphId).FirstOrDefault().Id</p><p>Paragraph Name:> @paragraphs.Where(s => s.Id == sectionParagraph.ParagraphId).FirstOrDefault().Name</p> } else {<p>End of Document.</p> }}<div class="dialog-buttons"> <button class="btn btn-secondary mr-auto" @onclick="GotoNextCheckParagraph">Next</button></div>@code{ int _currentIndex = 0; SectionParagraph sectionParagraph = new(); List<Paragraph> paragraphs; List<SectionParagraph> sectionParagraphs; List<Section> sections; protected override async Task OnInitializedAsync() { paragraphs = await HttpClient.GetFromJsonAsync<List<Paragraph>>(NavigationManager.BaseUri +"paragraphs"); sectionParagraphs = await HttpClient.GetFromJsonAsync<List<SectionParagraph>>(NavigationManager.BaseUri +"sectionparagraphs"); sections = await HttpClient.GetFromJsonAsync<List<Section>>(NavigationManager.BaseUri +"sections"); sectionParagraph = sectionParagraphs[0]; section = sections[0]; paragraph = paragraphs[0]; } private void GotoNextCheckParagraph() { // Read next paragraph // _currentIndex++; if (_currentIndex < sectionParagraphs.Count) { sectionParagraph = sectionParagraphs[_currentIndex]; } }}and one of the boilerplate Controller class looks like this.
[Route("sections")][ApiController]public class SectionController{ private readonly ReportContext _db; public SectionController(ReportContext db) { _db = db; } [HttpGet] public async Task<ActionResult<List<Section>>> GetSections() { return await (_db.Sections.ToListAsync()); }}
