Blazor .Net WASM UI .Net Coe 6.0 Web API With EF 6.0 Using Repository Pattern

Introduction

In this article, I am going to show you how to use the repository pattern while interacting with Sqlserver through EntityFramework.

Also, I will show how to use the repository pattern in your API controller which can be exposed at the UI client level for making the Blazor WASM user component.

First of all, I am back in C# Corner after 10 years with more experience and focus.

So now let's start. As we all know the Repository pattern are classes or components that encapsulate the logic required to access data sources.

They centralize common data access functionality, providing better maintainability and decoupling the infrastructure or technology used to access databases from the domain model layer. It gives you the flexibility to make your architecture more loosely couple for the TDD approach.

So now let's start a BLAZOR WASM Application using vs2022 (I am using vs2022)

Step 1 - Create Project

 

Use the below setting

Now you have the below 3 Project Settings (My application name is “BlazorApp1)

Now before working in server layer we need to create the Model class under “Shared” Project which can be reuse at Server and Client layer later

Step 2

Let’s create the two below classes 1.Grade.cs 2. Student.cs under the “Model” folder

Grade has 1 to many relationships with Student

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BlazorApp1.Shared.Model
{
    public class Grade
    {
        public int GradeId { get; set; }
        public string ? GradeName { get; set; }
        public List<Student>? Student { get; set; }
    }
}
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BlazorApp1.Shared.Model
{
    public class Student
    {
        [Key]
        public int Id { get; set; }
        public string? Name { get; set; }
        public int GradeId { get; set; }
        public Grade ?Grade { get; set; }
    }
}

We have created the model class as a Domain driven Development approach so that it will create the relationship table after running the migration

Step 3

Now work in Server Layer

First of all, create the DB context class under the “Data” folder which holds our POCO class Student and Grade

#nullable disable
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using BlazorApp1.Shared.Model;
namespace BlazorApp1.Server.Data
{
    public class BlazorApp1ServerContext : DbContext
    {
        public BlazorApp1ServerContext()
        {
        }
        public BlazorApp1ServerContext(DbContextOptions<BlazorApp1ServerContext> options)
            : base(options)
        {
        }
        public DbSet<Student> Student { get; set; }
        public DbSet<Grade> Grade { get; set; }
    }
}

Step 4

Entry Connection string at “appsettings.json”

"ConnectionStrings": {
    "BlazorApp1ServerContext": "Server=localhost\\SQLEXPRESS;Database=Blazor;Trusted_Connection=True;"

Step 5

Add dependency Injection for this connection string at “Program.cs”

builder.Services.AddDbContext<BlazorApp1ServerContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("BlazorApp1ServerContext")));

Step 6

Now execute the migration  from the npm packet manager

  1. Add-Migration “TableCreate”
  2. Update-Database

After executing the above command the below things will happen for the Migration

Now you have the table creation at SQL DB

Step 7

Now let's create the Repository pattern by creating first the “Repository” folder

Under this folder create the below 2 interface

using BlazorApp1.Shared.Model;
namespace BlazorApp1.Server.Repository.Interface
{
    public interface IGrade
    {
        public List<Grade> GetGradeDetails();
        public void AddGrade(Grade user);
        public void UpdateGradeDetails(Grade user);
        public Grade GetGradeData(int id);
        public void DeleteGrade(int id);
    }
}

using BlazorApp1.Shared.Model;
namespace BlazorApp1.Server.Repository.Interface
{
    public interface IStudent
    {
        public List<Student> GetStudentDetails();
        public void AddStudent(Student user);
        public void UpdateStuentDetails(Student user);
        public Student GetStudentData(int id);
        public void DeleteStudent(int id);
    }
}

So in our Interface for the Student and Grade we have our necessity contract which need to be implemented.

So we have created a “manager” Folder where we will implement our interface by using dependency injection for the DB context class which will interact with

Our table data

using BlazorApp1.Server.Data;
using BlazorApp1.Server.Repository.Interface;
using BlazorApp1.Shared.Model;
using Microsoft.EntityFrameworkCore;
namespace BlazorApp1.Server.Repository.Maneger
{
    public class GradeManager : IGrade
    {
        readonly BlazorApp1ServerContext _dbContext = new BlazorApp1ServerContext();
        public GradeManager(BlazorApp1ServerContext dbContext)
        {
            _dbContext = dbContext;
        }
        public List<Grade> GetGradeDetails()
        {
            return _dbContext.Grade.ToList();
        }
        public Grade GetGradeData(int id)
        {
            try
            {
                Grade? grade = _dbContext.Grade.Find(id);
                if (grade != null)
                {
                    return grade;
                }
                else
                {
                    throw new ArgumentNullException();
                }
            }
            catch
            {
                throw;
            }
        }
        public void AddGrade(Grade grade)
        {
            try
            {
                _dbContext.Grade.Add(grade);
                _dbContext.SaveChanges();
            }
            catch
            {
                throw;
            }
        }
        public void DeleteGrade(int id)
        {
            try
            {
                Grade? grade = _dbContext.Grade.Find(id);
                if (grade != null)
                {
                    _dbContext.Grade.Remove(grade);
                    _dbContext.SaveChanges();
                }
                else
                {
                    throw new ArgumentNullException();
                }
            }
            catch
            {
                throw;
            }
        }
        public void UpdateGradeDetails(Grade grade)
        {
            try
            {
                _dbContext.Entry(grade).State = EntityState.Modified;
                _dbContext.SaveChanges();
            }
            catch
            {
                throw;
            }
        }
    }
}

using BlazorApp1.Server.Data;
using BlazorApp1.Server.Repository.Interface;
using BlazorApp1.Shared.Model;
using Microsoft.EntityFrameworkCore;
namespace BlazorApp1.Server.Repository.Maneger
{
    public class StudentManager : IStudent
    {
        readonly BlazorApp1ServerContext _dbContext = new BlazorApp1ServerContext();
        public StudentManager(BlazorApp1ServerContext dbContext)
        {
            _dbContext = dbContext;
        }
        public Student GetStudentData(int id)
        {
            try
            {
                Student? student = _dbContext.Student.Find(id);
                if (student != null)
                {
                    return student;
                }
                else
                {
                    throw new ArgumentNullException();
                }
            }
            catch
            {
                throw;
            }

        }
        public List<Student> GetStudentDetails()
        {
            return _dbContext.Student.ToList();
        }
        public void AddStudent(Student student)
        {
            try
            {
                _dbContext.Student.Add(student);
                _dbContext.SaveChanges();
            }
            catch
            {
                throw;
            }
        }
        public void DeleteStudent(int id)
        {
            try
            {
                Grade? grade = _dbContext.Grade.Find(id);
                if (grade != null)
                {
                    _dbContext.Grade.Remove(grade);
                    _dbContext.SaveChanges();
                }
                else
                {
                    throw new ArgumentNullException();
                }
            }
            catch
            {
                throw;
            }
        }
        public void UpdateStuentDetails(Student user)
        {
            throw new NotImplementedException();
        }
    }
}

Step 8

So by using repository pattern we have created our DAL layer now we can create our API controller and can call the repository instance for accessing  our dto object

Before that we need to add our managerial class dependency injection at “Program.cs” class

builder.Services.AddTransient<IStudent, StudentManager>();
builder.Services.AddTransient<IGrade, GradeManager>();

Now let's create the Grade and Student API Controller which we will expose at Client-side UI operation

using Microsoft.AspNetCore.Mvc;
using BlazorApp1.Server.Repository.Interface;
using BlazorApp1.Shared.Model;
// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
namespace BlazorApp1.Server.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class GradeController : ControllerBase
    {
        private readonly IGrade _IGrade;
        public GradeController(IGrade iGrade)
        {
            _IGrade = iGrade;
        }
        // GET: api/<GradeController>
        [HttpGet]
        public async Task<List<Grade>> GetGradeDetails()
        {
            return await Task.FromResult(_IGrade.GetGradeDetails());
        }
        [HttpGet("{id}")]
        public IActionResult GetGradeDetailsbyId(int id)
        {
            Grade grade = _IGrade.GetGradeData(id);
            if (grade != null)
            {
                return Ok(grade);
            }
            return NotFound();
        }
        [HttpPost]
        public void Post(Grade grade)
        {
            _IGrade.AddGrade(grade);
        }
        [HttpPut]
        public void Put(Grade grade)
        {
            _IGrade.UpdateGradeDetails(grade);
        }
        [HttpDelete("{id}")]
        public IActionResult Delete(int id)
        {
            _IGrade.DeleteGrade(id);
            return Ok();
        }
    }
}
using BlazorApp1.Server.Repository.Interface;
using BlazorApp1.Shared.Model;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace BlazorApp1.Server.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class StudentsController : ControllerBase
    {
        private readonly IStudent _IStudent;
        public StudentsController(IStudent iStudent)
        {
            _IStudent = iStudent;
        }
        // GET: api/<GradeController>
        [HttpGet]
        public async Task<List<Student>> GetGradeDetails()
        {
            return await Task.FromResult(_IStudent.GetStudentDetails());
        }
        [HttpGet("{id}")]
        public IActionResult GetStudentDetailsbyId(int id)
        {
            Student student = _IStudent.GetStudentData(id);
            if (student != null)
            {
                return Ok(student);
            }
            return NotFound();
        }
        [HttpPost]
        public void Post(Student student)
        {
            _IStudent.AddStudent(student);
        }
        [HttpPut]
        public void Put(Student student)
        {
            _IStudent.UpdateStuentDetails(student);
        }
        [HttpDelete("{id}")]
        public IActionResult Delete(int id)
        {
            _IStudent.DeleteStudent(id);
            return Ok();
        }
    }
}

See in the controller we have constructor dependency injection for our Repository Interface class and from there we are accessing our DAL Managerial class for both Student and Grade manager DAL class layer.

In our next article, I will show you how to use this API controller at the Client UI side for the data operation. Till then happy coding 😊