This source provides a comprehensive tutorial on building an ASP.NET Core 8 MVC (Model-View-Controller) application from the ground up, focusing on CRUD (Create, Read, Update, Delete) operations. It guides the user through setting up a SQL Server database using Entity Framework Core, covering topics such as project creation, dependency injection, database migrations, and the implementation of web pages for managing student data. The tutorial also explains how to design views with Bootstrap and handle HTTP GET/POST requests for each CRUD function, including troubleshooting common issues like Entity Framework Core tracking errors.
ASP.NET Core MVC: Student Data CRUD with Entity Framework
CRUD operations, which stand for Create, Read, Update, and Delete, are fundamental functionalities for managing data in most web and API applications. The sources describe building an ASP.NET Core 8 MVC application from scratch to perform these operations on student data stored in a SQL Server database using Entity Framework Core.
Here’s a detailed discussion of each CRUD operation as implemented in the described application:
- Create (Add Student)
- Purpose: To allow users to add new student records to the database.
- User Interface: An “Add student page” is created, featuring form inputs for the student’s name, email, phone, and a subscribed option (a boolean checkbox).
- Controller (StudentsController):An HTTP GET Add action method is used to display the initial add student form.
- An HTTP POST Add action method handles the form submission. This method receives an AddStudentViewModel as a parameter, which encapsulates the data entered by the user (name, email, phone, subscribed).
- Data Handling:A Student entity class is defined with properties like ID (a unique identifier, automatically set by Entity Framework Core), Name, Email, Phone Number, and Subscribed (a boolean).
- The ApplicationDBContext class, which acts as a bridge between Entity Framework Core and the SQL Server database, is injected into the controller using Constructor Injection.
- Inside the POST Add method, a new Student entity is created using the data from the AddStudentViewModel.
- The DBContext.Students.AddAsync() method is used to add the new student entity to the context.
- Finally, DBContext.SaveChangesAsync() is called to persist the changes to the SQL Server database.
- Read (List Students)
- Purpose: To display a list of all students currently stored in the database.
- User Interface: An “All students web page” is created, which shows the ID, name, and email of each student in a table format. Each row also includes an “Edit” button.
- Controller (StudentsController):An HTTP GET List action method is responsible for retrieving and displaying the student list.
- Data Handling:The DBContext is used to access the Students collection.
- The await DBContext.Students.ToListAsync() method retrieves all student records from the database.
- This list of Student entities is then passed to the List.cshtml view.
- View (List.cshtml): The view is strongly typed to a List<Student> and uses a foreach loop to iterate through the collection and display each student’s details in a table. A navigation link to “All Students” is also added to the application’s layout page.
- Update (Edit Student)
- Purpose: To allow users to view and modify the details of an existing student record.
- User Interface: An “Edit student web page” is used, which looks similar to the add student page but is pre-populated with the selected student’s current information. The ID field is displayed as read-only.
- Linking: The “Edit” button on the “All Students” list page is configured to pass the unique ID of the specific student to the edit page’s URL (e.g., /students/edit/{id}).
- Controller (StudentsController):An HTTP GET Edit action method takes the student’s ID (GUID) as a parameter. It uses await DBContext.Student.FindAsync(ID) (or FirstOrDefaultAsync) to retrieve the student’s current information from the database. If no student is found for the given ID (e.g., it’s a junk ID), a “no student found” message can be displayed. The retrieved Student entity is then passed to the Edit.cshtml view.
- An HTTP POST Edit action method receives an updated Student model (or AddStudentViewModel) from the submitted form.
- It first retrieves the existing student record from the database using its ID.
- Important Note: The source initially used FindAsync, which caused tracking issues during deletion. It was later modified to use DBContext.Students.FirstOrDefaultAsync(x => x.ID == viewModel.ID).AsNoTracking() to avoid Entity Framework Core tracking the entity, ensuring proper deletion later.
- The properties of the retrieved student entity (name, email, phone, subscribed) are then updated with the new values from the submitted view model.
- await DBContext.SaveChangesAsync() is called to save these updated details to the database.
- After a successful update, the user is redirected back to the “All Students” list page (RedirectToAction(“List”, “Students”)).
- Delete (Delete Student)
- Purpose: To remove a student record permanently from the database.
- User Interface: A “Delete” button is added to the “Edit student page”. It is styled with a “danger” class to indicate its destructive action.
- Controller (StudentsController):An HTTP POST Delete action method is created, which takes the student’s ID (via a Student view model) as a parameter.
- Data Handling:The method retrieves the student entity to be deleted using await DBContext.Students.FirstOrDefaultAsync(x => x.ID == viewModel.ID).AsNoTracking(). The .AsNoTracking() is crucial here to prevent Entity Framework Core from tracking the entity, which caused errors when attempting to remove an already tracked instance.
- A check is performed to ensure the student exists (is not null).
- DBContext.Students.Remove(student) is called to mark the entity for deletion.
- await DBContext.SaveChangesAsync() is then executed to commit the deletion to the database.
- After deletion, the user is redirected back to the “All Students” list page.
These CRUD operations demonstrate the full lifecycle of data management within an ASP.NET Core MVC application, leveraging Entity Framework Core as an ORM (Object-Relational Mapper) to interact with the SQL Server database without writing raw SQL queries. Entity Framework Core handles database connections, instance management, and synchronization between the application’s models and the database tables through techniques like migrations.
ASP.NET Core 8 MVC CRUD with Entity Framework Core
ASP.NET Core is a powerful and modern framework for building web applications and APIs. The sources describe its use in creating a beginner-friendly ASP.NET Core 8 MVC application from scratch to perform CRUD (Create, Read, Update, Delete) operations on student data stored in a SQL Server database using Entity Framework Core.
Here’s a discussion of ASP.NET Core based on the provided information:
- Core Purpose and Application Type
- ASP.NET Core is used to create web applications, specifically an MVC (Model-View-Controller) application in the context of the tutorial. It uses the C# language for development.
- The goal of the described application is to manage student data, allowing users to add, list (view), edit, and delete student records.
- Project Setup and Structure
- A new .NET 8 application is created using the MVC template in Visual Studio.
- An ASP.NET Core MVC application by default provides the following key folders: Models, Views, and Controllers.
- The Program.cs file is the main file for configuring the application, where services like controllers with views are added to the Builder object.
- The launchSettings.json file in the Properties folder contains launch-related settings, including URLs for the server to run on.
- MVC Architecture
- Controllers: These contain action methods (e.g., Index, Privacy, Add, List, Edit, Delete) which handle incoming requests. They are typically decorated with HTTP GET or HTTP POST attributes to specify the type of request they handle. Action methods can be made asynchronous (async Task<IActionResult>) for operations that involve waiting for I/O, such as database interactions.
- Views: These are .cshtml (Razor View) files located in folders corresponding to their controllers (e.g., Views/Home for HomeController, Views/Students for StudentsController). They contain HTML markup and can be strongly typed to a model (e.g., AddStudentViewModel, List<Student>, Student) using the @model directive. Bootstrap classes are widely used for styling the HTML elements.
- Models: These represent the data structures. The application defines Student entity classes (within a Models/Entities folder) with properties like ID (a unique identifier, often a GUID), Name, Email, PhoneNumber, and Subscribed (a boolean flag). View Models (e.g., AddStudentViewModel) are also used to encapsulate data passed between views and controllers, separating it from the domain entities.
- Routing: By default, routes are configured to map URLs to controller action methods (e.g., /Home/Index is the default homepage). Links between pages often use ASP tags (e.g., asp-controller, asp-action, asp-route-id) to generate correct URLs.
- Key Features and Development Flow
- Hot Reloading: Visual Studio automatically refreshes the application in the browser to reflect changes saved in the code, improving development speed.
- Dependency Injection: ASP.NET Core uses constructor injection to provide instances of classes, such as the ApplicationDBContext, to controllers. This means you don’t have to manually “new up” instances, as the framework handles it.
- Integration with Entity Framework Core (EF Core):EF Core is a micro ORM (Object-Relational Mapper) that simplifies interaction with databases like SQL Server. It handles database connections and instances, allowing direct interaction with tables through C# classes.
- NuGet packages like Microsoft.EntityFrameworkCore.SqlServer and Microsoft.EntityFrameworkCore.Tools are installed to enable EF Core functionality and migrations.
- A DBContext class (e.g., ApplicationDBContext) acts as a bridge between EF Core and the database. It inherits from DBContext and contains DbSet properties (e.g., DbSet<Student> Students) which represent collections that map to database tables.
- Connection strings are defined in appsettings.json and tell the application which SQL Server instance and database to use.
- Migrations are used to create and update the database schema based on the application’s entity models. Commands like Add-Migration [name] and Update-Database are run in the Package Manager Console to create migration files and then apply them to the database. This ensures the database schema stays in sync with the application’s models.
- EF Core methods like AddAsync(), ToListAsync(), FindAsync(), FirstOrDefaultAsync(), Remove(), and SaveChangesAsync() are used within controllers to perform the actual CRUD operations by interacting with the DBContext.
- The .AsNoTracking() method can be crucial when retrieving entities for operations like deletion to prevent EF Core from tracking the entity, which can lead to errors if another instance with the same key is already being tracked.
Mastering Entity Framework Core in ASP.NET Applications
Entity Framework Core (EF Core) is a powerful and essential component within the ASP.NET Core ecosystem, primarily functioning as a micro ORM (Object-Relational Mapper) . Its core purpose is to simplify how ASP.NET Core applications interact with databases, such as **SQL Server**, by allowing developers to work with database tables directly through **C# classes (entities)** rather than writing raw SQL queries.
Here’s a detailed discussion of Entity Framework Core based on the sources:
- Role as an ORM
- EF Core makes a developer’s life “very easy” because it handles all the database connections and instances . This means you can interact with database tables directly using C# code.
- It effectively bridges the gap between your C# application’s models and the underlying SQL Server database “.
- Installation and Setup
- To integrate EF Core into an ASP.NET Core project, specific NuGet packages must be installed “. The sources mention:
- Microsoft.EntityFrameworkCore.SqlServer: For connecting to SQL Server databases “.
- Microsoft.EntityFrameworkCore.Tools: This package is crucial for migrations, which are used to create and update the database schema “.
- The DBContext Class: The Bridge to the Database
- A DBContext class (e.g., ApplicationDBContext) is created, which inherits from DBContext (from Microsoft.EntityFrameworkCore) . This class serves as the **bridge between Entity Framework Core and the database**.
- Within the DBContext class, DbSet properties are defined . These properties (e.g., `DbSet<Student> Students`) represent **collections** and are used to **reference and access the tables** in the SQL Server database.
- The DBContext is made available throughout the application using Dependency Injection . It is configured in `Program.cs` using `builder.Services.AddDbContext`, where it’s also told which database to use (e.g., options.UseSqlServer) “.
- Connection Strings
- EF Core needs to know how to connect to the database. This is achieved by defining a connection string “.
- Connection strings are stored in the appsettings.json file . They are key-value pairs, where the key can be descriptive (e.g., “StudentPortal”) and the value contains details like the **server name, database name**, and connection properties (e.g., `trusted_connection=true`, `trustServerCertificate=true`).
- The application retrieves the connection string from appsettings.json using Builder.Configuration.GetConnectionString in Program.cs “.
- Migrations: Synchronizing Database Schema
- Migrations are a key feature of EF Core that allow the database schema to stay in sync with the application’s entity models “.
- They are executed via the Package Manager Console in Visual Studio “.
- The process involves two main commands “:
- Add-Migration [name]: This command creates a migration file (e.g., InitialMigration.cs) . This file contains C# code generated by EF Core that describes the changes needed to create or update the database table(s) based on your `DbSet` properties and entity models. For example, it would define a Students table with ID, Name, Email, Phone, and Subscribed columns “.
- Update-Database: This command applies the pending migrations to the actual SQL Server database . If the database doesn’t exist, it will be created; otherwise, it will be updated to match the application’s models.
- Performing CRUD Operations with EF Core
- EF Core provides asynchronous methods for performing Create, Read, Update, and Delete operations “:
- Create (Add): New entities (e.g., a Student object) are added to the DBContext using DBContext.Students.AddAsync() . The changes are then persisted to the database by calling `await DBContext.SaveChangesAsync()`.
- Read (List and Single):
- To retrieve a list of all students, await DBContext.Students.ToListAsync() is used “.
- To find a single student by its unique ID, methods like await DBContext.Students.FindAsync(ID) or await DBContext.Students.FirstOrDefaultAsync(x => x.ID == viewModel.ID) are employed “.
- Update: An existing entity is first retrieved from the database. Its properties are then updated with new values from a view model. The changes are saved to the database by calling await DBContext.SaveChangesAsync() “.
- Delete: The entity to be deleted is retrieved, and then DBContext.Students.Remove(student) is called to mark it for deletion . `await DBContext.SaveChangesAsync()` then commits this deletion to the database.
- Handling Tracking Issues (AsNoTracking())
- A significant detail highlighted in the sources is the use of .AsNoTracking() “.
- When retrieving an entity using FindAsync or FirstOrDefaultAsync, EF Core tracks that entity . This can lead to errors, especially during deletion, if another instance with the same key is already being tracked.
- By adding .AsNoTracking() to the query (e.g., DBContext.Students.FirstOrDefaultAsync(x => x.ID == viewModel.ID).AsNoTracking()), you prevent EF Core from tracking the retrieved entity, which resolves conflicts and allows the Remove operation to proceed without error “.
In summary, Entity Framework Core streamlines database interactions in ASP.NET Core applications by providing an object-oriented way to manage data, handling complex tasks like schema synchronization through migrations, and offering a robust API for performing all fundamental CRUD operations “.

By Amjad Izhar
Contact: amjad.izhar@gmail.com
https://amjadizhar.blog
Affiliate Disclosure: This blog may contain affiliate links, which means I may earn a small commission if you click on the link and make a purchase. This comes at no additional cost to you. I only recommend products or services that I believe will add value to my readers. Your support helps keep this blog running and allows me to continue providing you with quality content. Thank you for your support!


