Objective of this Tutorial
We shall have a simple form of one textbox for inserting a record into a database.
The backend database will be Sqlite.
The saved data is not displayed in this tutorial. We reserve that for some future tutorial.
Video Explanation with a Working Example
Please watch the following youtube video:
Step 1 of 6: Decide your Database and add its Nuget Package
We shall use sqlite database, but you can use any. Except the connection string everything else remains the same.
Add its nuget package as explained in the previous tutorial - "Various Database Options and the initial Setup"
Step 2 of 6: Decide on the Model
A model maps to a table in your database.
Create a folder called "Models" and add a class called Product
to it.
A model must contain a primary key, and, therefore, a property called ID or a property suffixed with ID or a property marked with the attribute [Key]
has to be added to a model class.
using Microsoft.EntityFrameworkCore; using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Diagnostics.CodeAnalysis; public class Product { // auto-increment Primary ID key [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int ID { get; set; } // just one property public String Name { get; set; } }
Step 3 of 6: Write your DAL based on DbContext
(see the linked video for details)
Data access layer [DAL] is written by inheriting a class from the readymade DbContext class.
DbContext represents your entire database - there is one DbContext for a whole physical database.
The class must contain a default constructor with DbContextOptions
.
You must override the OnModelCreating
method to specify foreign key constraints, indexes, and the names of database tables for each model. The names of the tables are useful if you have to run direct SQL queries against your database.
The last important thing is the DbSet
collection property corresponding to each model (i.e., table) in the database. The name of this property must be pluralized - like for example, Products
. A DbSet
represents a [virtual] collection of the records of your table. Records can be added and queried by using various methods like Insert, Add, Update, etc., that are available on dotnet collections. A modified record, for example, is internally marked dirty, and, on Save(), the EF framework runs an UPDATE SQL query on the physical database.
Add the following ProductContext class. This class can be added in the same file as one of the models, or a different file depending on the complexity of your project.
using Microsoft.EntityFrameworkCore; using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Diagnostics.CodeAnalysis; // dbcontext DAL - THERE IS ONE DbContext per database public class ProductContext : DbContext { public ProductContext(DbContextOptions options) : base(options) { // EnsureCreated is meant for testing or creating // a blank database. this code should be avoided // at this place. use some alternate program to // create/migrate your database. this code has been // used here only for tutorial purposes Database.EnsureCreated(); } // this function is used to specify FK relations, Indexes, // and [optionally] the name of your database tables // corresponding to each model protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); // name of the table in your database modelBuilder.Entity<Product>().ToTable("product"); } // MUST be PLURAL public DbSet<Product> Products { get; set; } // more DbSet are added here - one for // each model (i.e., table) }
Step 4 of 6: Dependency Injection of the ProductContext
An instance of the ProductContext is required for executing database queries.
The best way is to obtain it is through Dependency Injection. The ASPNET framework can make it available to us through the constructor of a class whenever we need it (see Step 5 below).
Add a line to the ConfigureServices method of the Startup class and specify your connection string also:
using DBaseCon; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; namespace Modular { public class Startup { public void ConfigureServices(IServiceCollection services) { // make an arrangement for DependencyInjection // of ProductContext instance. the database is // created in the root directory of your project // alternately create a folder, say, DBase and then // specify the path as DBase/mydb.db services.AddDbContext<ProductContext>( opt => opt.UseSqlite("Data Source=mydb.db")); // add support for razor pages services.AddRazorPages(); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseRouting(); app.UseEndpoints(endpoints => { // add razor pages as the end-points endpoints.MapRazorPages(); }); } } }
Step 5 of 6: Grabbing the ProductContext
(see the linked video for details)
ProductContext
can be obtained in the constructor of your PageModel class.
A 2-way property binding is required for your data-entry form. This property contains the form data when a user fills the form and submits it.
A form submit is handled through the OnPost method of the PageModel class.
In the OnPost method, save the record to the database as shown below. Since the record is a new record, an INSERT query will be run by the EF Core.
Complete the backing class file Index.cshtml.cs thus:
using DBaseCon; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; namespace Modular.Pages { public class IndexModel : PageModel { private readonly ProductContext _ctx; // dependency injection of the ProductContext public IndexModel(ProductContext ctx) { _ctx = ctx; } // 2-way binding [BindProperty] public Product Prod { get; set; } // save the posted form data // in the OnPost handler // NOTE: strictly speaking, this method // must be asynchronous. we shall make // that correction in later tutorials public ActionResult OnPost() { _ctx.Products.Add(Prod); _ctx.SaveChanges(); // redirect and show the // form again return RedirectToPage(); } } }
Step 6 of 6: Complete the Data Entry Form
(see the linked video for details)
Write this into the Index.cshtml razor page file:
@page @model Modular.Pages.IndexModel @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers <form method="post"> Name: <input asp-for="Prod.Name" /> <input type="submit" /> </form>
This Blog Post/Article "(C# ASP.NET Core) Getting Started with Database INSERT of Form data" by Parveen is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.