Search  
RU EN

.NET Core — The simple step-by-step guide to creating and using a Generic Repository

Author:
Daniel Kreider
Source:
Views:
7595
.NET Core — The simple step-by-step guide to creating and using a Generic Repository favorites 0

Here’s the simple step-by-step guide that will teach you how to build and code a generic repository.

There are oodles of design patterns.

Some of these design patterns are floating about on antique blogs full of mad logic. They’re ridiculous enough to make the entire modern cloud rub its belly in roars of laughter.

Other design patterns are worth their dough.

And one of these is the repository pattern.

Of all the design patterns that I’ve studied and used when creating .NET Core applications, the repository pattern has never failed me.

And I’m tickled that you’re here to learn how to create and use a generic repository.

If you just want the code, the run over to this Github repository.

Otherwise, hang in there and I’ll explain this whole generic repository thing step by step. We’ll be building a pimple-simple web API server with .NET Core and Entity Framework Core.

Creating the data models (or entities)

The first building block needed for a great generic repository is a base model that the rest of our entities will inherit from. I’ve found that the advantages of a base entity can be… almost… endless. Most importantly it will give us a stable, base type that we can build our other entities with and also reference in our generic repository.

So the very first step is to create a file named BaseModel.cs and here's the code.

using System;

namespace GenericRepositoryDemo.Entities
{
    public class BaseModel
    {
        public Guid Id { get; set; }
        public DateTime Created { get; set; }
        public DateTime Updated { get; set; }
    }
}

This model will be our base entity with all the common information like primary key, created and updated information. And all other entities will inherit from it.

We’ll be working with two more entities — the blog entity and the post entity.

Here’s the code. And please notice how we’re inheriting from the BaseModel.

using System.Collections.Generic;

namespace GenericRepositoryDemo.Entities
{
    public class Blog : BaseModel
    {
        public int BlogId { get; set; }
        public string Url { get; set; }
        public List<Post> Posts { get; } = new List<Post>();
    }
}

 

namespace GenericRepositoryDemo.Entities
{
    public class Post : BaseModel
    {
        public string Title { get; set; }
        public string Content { get; set; }
        public int BlogId { get; set; }
        public Blog Blog { get; set; }
    }
}

And now that we’ve created our entities for EF Core, we’re ready to set up Entity Framework by using a database context.

Setting up Entity Framework Core

If you created your project with the .NET Core CLI then you probably already have a ApplicationDbContext ready to be setup and used.

You’ll want to add your new entities to the database context like so.

using System.Collections.Generic;
using GenericRepositoryDemo.Entities;
using Microsoft.EntityFrameworkCore;

namespace GenericRepositoryDemo
{
    public class BloggingContext : DbContext
    {
        public DbSet<Blog> Blogs { get; set; }
        public DbSet<Post> Posts { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder options)
            => options.UseSqlite("Data Source=blogging.db");
    }
}

I’m assuming you know the basics of EF Core, and we’ll move on to creating our generic repository. But if you need it, Microsoft has great documentation on installing and configuring EF Core.

And now that we’ve got all the other needed pieces ready, we can start building our generic repository.

Creating the Generic Repository

Create a new file (also called class) named GenericRepository.cs. Then steal the code below. 😎

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using GenericRepositoryDemo.Entities;
using Microsoft.EntityFrameworkCore;

namespace GenericRepositoryDemo.Repositories
{
    public class GenericRepository<Entity> where Entity : BaseModel
    {
        private readonly BloggingContext _context;
        private DbSet<Entity> _dbSet;
        public GenericRepository(BloggingContext context)
        {
            _context = context;
            _dbSet = _context.Set<Entity>();
        }

        public async Task<List<Entity>> GetAllAsync()
        {
            return await _dbSet.ToListAsync();
        }

        public async Task<Entity> GetAsync(Guid id)
        {
            return await _dbSet.FirstOrDefaultAsync(e => e.Id == id);
        }

        public async Task CreateAsync(Entity entity)
        {
            await _dbSet.AddAsync(entity);
        }

        public void Update(Entity entity)
        {
            _dbSet.Update(entity);
        }

        public void Delete(Entity entity)
        {
            _dbSet.Remove(entity);
        }

        public async Task SaveChangesAsync()
        {
            await _context.SaveChangesAsync();
        }
    }
}

So what have we done?

First, we’ve created a generic repository that requires a type of BaseModel. And then we've added the basic CRUD operations for that entity.

But we’re not quite done. The last step that’s needed is to add our generic repository as an injectable service.

So we’ll edit our Startup.cs file, and make it look like this.

public void ConfigureServices(IServiceCollection services)
{
    // ... other stuff
    services.AddTransient(typeof(GenericRepository<>));
}

Yes buddy! This is coming together!

But how do we use our budding, brand new generic repository?

Using the Generic Repository

Let’s create a CRUD controller for the Blog entity, and use the generic repository to handle data access.

Here’s what it looks like.

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using GenericRepositoryDemo.Entities;
using GenericRepositoryDemo.Repositories;
using Microsoft.AspNetCore.Mvc;

namespace GenericRepositoryDemo.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class BlogController : ControllerBase
    {
        private readonly GenericRepository<Blog> _repository;
        public BlogController(GenericRepository<Blog> repository)
        {
            _repository = repository;
        }

        [HttpGet]
        public async Task<List<Blog>> GetAllAsync()
        {
            return await _repository.GetAllAsync();
        }

        [HttpGet("{id}")]
        public async Task<Blog> GetAsync(Guid id)
        {
            return await _repository.GetAsync(id);
        }

        [HttpPost]
        public async Task CreateAsync([FromBody] Blog blog)
        {
            await _repository.CreateAsync(blog);
            await _repository.SaveChangesAsync();
        }

        [HttpPut]
        public async Task UpdateAsync([FromBody] Blog blog)
        {
            _repository.Update(blog);
            await _repository.SaveChangesAsync();
        }

        [HttpDelete]
        public async Task DeleteAsync([FromBody] Blog blog)
        {
            _repository.Delete(blog);
            await _repository.SaveChangesAsync();
        }
    }
}

Conclusion

And this, my friend, concludes the simple guide that will teach you how to code and use a generic repository.

Data access is one of the core pieces in many applications.

And when used properly, a generic repository is a great tool for getting the data access.

Similar
Jul 25, 2023
Unleashing the Power of Meta-Programming: A Comprehensive Guide to C# Reflection Reflection, put simply, is a mechanism provided by the .NET framework that allows a running program to examine and manipulate itself. It’s like a coding mirror that gives your...
Nov 22, 2024
Author: Sylvain Tiset
Earlier I presented one useful design pattern to migrate to a monolithic application to microservices. This pattern is the Strangler Fig pattern and the article can be found here. Here some other specific microservices design patterns will be presented. What...
Feb 5, 2024
Author: Crafting-Code
Lesser-known techniques for optimizing SQL queries in a high-traffic application, especially when dealing with complex joins and indexing challenges The success of high-traffic applications hinges on the efficient performance of their underlying databases. As the complexity of SQL queries grows,...
Dec 1, 2023
Author: Rico Fritzsche
The flight monitor case study: Applying Vertical Slices in a real-world scenario In my last articles I talked about Vertical Slice Architecture and how to organize code in a non-technical way. I showed some simple examples of how to do...
Send message
Type
Email
Your name
*Message