How to use Repository Pattern in C#

This tutorial shows you how to use Repository Pattern in ASP.NET Core using C#.NET.

What is Repository Pattern? How to use it in ASP.NET Core using c# code.

The Repository Pattern is simply an intermediate layer between the business layer and the data access layer. If you use Entity Framework in ASP.NET Core MVC or in ASP.NET MVC then business is the business processing layer, and Data is the layer used to contain the DbContext classes and entity classes.

In ASP.NET, the repository will be used to adjust the data before the data is transmitted to the business logic or transmitted to the data layer.

Benefits of using Repository Pattern

  • Easy to unit test
  • Flexible architecture
  • Reducing excess code.
  • Splitting helps to manage and make projects more effective
  • If there is a change in the business or data layer, there is no need to change Repository
  • Business logic and data processing are centralized.

Using Repository Pattern in ASP.NET Core

In this section, I will use the example of the Student.cs class to guide you. The Student.cs class will include the following code snippets:

public class Student
{
    public int ID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
}

Create an IStudent interface

public interface IStudent
{
    Task<Student> Get(int? id);
    bool Exists(int id);
    Task<List<Student>> GetAll();
    Task Add(Student model);
    Task Update(Student model);
    Task Delete(int id);
}

Creating a StudentRepository class that inherits from IStudent interface

public class StudentRepository : IStudent
{
    protected readonly ApplicationDbContext _context;

    public StudentRepository(ApplicationDbContext context)
    {
        _context = context;
    }

    public async Task Add(Student model)
    {
        _context.Add(model);
        await Save();
    }

    public async Task<Student> Get(int? id)
    {
        return await _context.Student.Where(c => c.ID == id).SingleOrDefaultAsync();
    }

    public bool Exists(int id)
    {
        return _context.Student.Any(c => c.ID == id);
    }

    public async Task<List<Student>> GetAll()
    {
        return await _context.Student.ToListAsync();
    }

    public async Task Update(Student Entity)
    {
        _context.Student.Update(Entity);
        await Save();
    }

    public async Task Delete(int id)
    {
        var temp = await _context.Student.SingleOrDefaultAsync(m => m.ID == id);
        _context.Student.Remove(temp);
        await Save();
    }

    private async Task Save()
    {
        await _context.SaveChangesAsync();
    }
}

Adding your repository to the application services

public void ConfigureServices(IServiceCollection services)
{
     services.AddApplicationInsightsTelemetry(Configuration);
     services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

     services.AddIdentity<ApplicationUser, IdentityRole>()
                .AddEntityFrameworkStores<ApplicationDbContext>()
                .AddDefaultTokenProviders();

     services.AddMvc();

     services.AddScoped<IStudent,StudentRepository>();
}

We will create a controller called StudentController, you can also use Entity Framework to create it quickly and replace your code with the following code:

public class StudentController : Controller
{
    private readonly IStudent _context;

    public StudentController(IStudent context)
    {
        _context = context;
    }

    // GET: Students
    public async Task<IActionResult> Index()
    {
        return View(await _context.GetAll());
    }

    // GET: Students/Details/5
    public async Task<IActionResult> Details(int? id)
    {
        if (id == null)
        {
            return NotFound();
        }

        var student = await _context.Get(id);
        if (student == null)
        {
            return NotFound();
        }

        return View(student);
    }

    // GET: Students/Create
    public IActionResult Create()
    {
        return View();
    }

    // POST: Students/Create
    // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
    // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Create([Bind("ID,Email,FirstName,LastName")] Student student)
    {
        if (ModelState.IsValid)
        {
            await _context.Add(student);
            return RedirectToAction("Index");
        }
        return View(student);
    }

    // GET: Students/Edit/5
    public async Task<IActionResult> Edit(int? id)
    {
        if (id == null)
        {
            return NotFound();
        }

        var student = await _context.Get(id);
        if (student == null)
        {
            return NotFound();
        }
        return View(student);
    }

    // POST: Students/Edit/5
    // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
    // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Edit(int id, [Bind("ID,Email,FirstName,LastName")] Student student)
    {
        if (id != student.ID)
        {
            return NotFound();
        }

        if (ModelState.IsValid)
        {
            try
            {
                await _context.Update(student);
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!StudentExists(student.ID))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }
            }
            return RedirectToAction("Index");
        }
        return View(student);
    }

    // GET: Students/Delete/5
    public async Task<IActionResult> Delete(int? id)
    {
        if (id == null)
        {
            return NotFound();
        }

        var student = await _context.Get(id);
        if (student == null)
        {
            return NotFound();
        }

        return View(student);
    }

    // POST: Students/Delete/5
    [HttpPost, ActionName("Delete")]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> DeleteConfirmed(int id)
    {
        await _context.Delete(id);
        return RedirectToAction("Index");
    }

    private bool StudentExists(int id)
    {
        return _context.Exists(id);
    }
}

Using a repository pattern will help a lot for your project.