Post

C# | Entity Framework Generic Repository with SOLID Design Pattern

Entity Framework Generic Repository with SOLID Design Pattern in C#

In this guide, we’ll explore how to create a generic repository in a C# application using Entity Framework while adhering to SOLID design principles. A generic repository allows you to interact with the database in a more organized and reusable manner.

Prerequisites

Before you begin, ensure you have the following prerequisites:

  • Basic knowledge of C# and Entity Framework.
  • An existing C# project with Entity Framework setup.

SOLID Design Principles

We’ll focus on the following SOLID principles:

  1. Single Responsibility Principle (SRP): Each class should have a single reason to change.
  2. Open-Closed Principle (OCP): Software entities (classes, modules, functions) should be open for extension but closed for modification.
  3. Liskov Substitution Principle (LSP): Subtypes must be substitutable for their base types.
  4. Interface Segregation Principle (ISP): A client should not be forced to implement interfaces they do not use.
  5. Dependency Inversion Principle (DIP): High-level modules should not depend on low-level modules. Both should depend on abstractions.

Creating a Generic Repository

  1. Create a Generic Repository Interface:
    1
    2
    3
    4
    5
    6
    7
    8
    
    public interface IRepository<T> where T : class
    {
        Task<T> GetByIdAsync(int id);
        Task<IEnumerable<T>> GetAllAsync();
        Task AddAsync(T entity);
        Task UpdateAsync(T entity);
        Task DeleteAsync(T entity);
    }
    
  2. Implement the Generic Repository:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    
    public class Repository<T> : IRepository<T> where T : class
    {
        private readonly DbContext _context;
    
        public Repository(DbContext context)
        {
            _context = context;
        }
    
        public async Task<T> GetByIdAsync(int id)
        {
            return await _context.Set<T>().FindAsync(id);
        }
    
        public async Task<IEnumerable<T>> GetAllAsync()
        {
            return await _context.Set<T>().ToListAsync();
        }
    
        public async Task AddAsync(T entity)
        {
            await _context.Set<T>().AddAsync(entity);
        }
    
        public async Task UpdateAsync(T entity)
        {
            _context.Set<T>().Update(entity);
        }
    
        public async Task DeleteAsync(T entity)
        {
            _context.Set<T>().Remove(entity);
        }
    }
    

Using the Generic Repository

  1. Dependency Injection: In your application’s startup or configuration, inject the repository into your services.

    1
    
    services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
    
  2. Using the Repository: In your services or controllers, use the generic repository to interact with the database.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
    public class MyService
    {
        private readonly IRepository<MyEntity> _repository;
    
        public MyService(IRepository<MyEntity> repository)
        {
            _repository = repository;
        }
    
        public async Task<MyEntity> GetEntityById(int id)
        {
            return await _repository.GetByIdAsync(id);
        }
    
        // Implement other methods as needed
    }
    
  3. Apply SOLID Principles: Ensure your services adhere to SOLID principles, like separating concerns and following the Single Responsibility Principle, when implementing business logic.

What Next?

Creating a generic repository using Entity Framework and adhering to SOLID design principles can make your C# application more maintainable and scalable. By using this pattern, you can easily extend and modify your data access layer without affecting the rest of your application. Remember to adapt the code and principles to your specific project’s needs and requirements.

This post is licensed under CC BY 4.0 by the author.