Design Patterns - Repository Pattern in C# using Entity Framework Core

Before you look at the Repository pattern example in C# using Entity Framework Core, you can see my post about what is the Repository pattern.

Example of the generic repository interface in C#

public interface IRepository<T> where T : IAggregateRoot
{
  IImmutableList<T> FindAll();

  T Find(Guid id);

  IImmutableList<T> Where(Expression<Func<T, bool>> predicate);
}

About this code snippet:

  • T extends from IAggregateRoot, so it forces the generic repository to work with Aggregate Roots instead of Entities.
  • Methods don’t return IQueryable, but must materialize the query results before returning them.
  • The methods FindAll and Where return IImmutableList.

Example of the specialized repository interface in C#

public interface IUsersRepository : IRepository<User>
{
  void Add(User user);

  void Remove(User user);
}

About this code snippet:

  • In this example the entity User can be created and removed, so the specialized repository has methods for that.

Example of the implementation of the specialized repository in C# using Entity Framework Core

public sealed class UsersRepository : IUsersRepository
{
  private DbSet<User> _dbSet { get; }

  public UsersRepository(ApplicationDbContext context)
  {
    this._dbSet = context.Set<User>();
  }

  public IImmutableList<User> FindAll()
  {
    return this._dbSet.ToImmutableList();
  }

  public User Find(Guid id)
  {
    return this._dbSet.Find(id);
  }

  public IImmutableList<User> Where(Expression<Func<User, bool>> predicate)
  {
    return this._dbSet.Where(predicate).ToImmutableList();
  }

  public void Add(User user)
  {
    this._dbSet.Add(user);
  }

  public void Remove(User user)
  {
    this._dbSet.Remove(user);
  }
}

About this code snippet:

  • It extends from the specialized repository.
  • It requires DbContext in its constructor arguments (Which is injected with dependency injection) but just uses DbSet<User> from it.
  • DbSet<User> is already a repository provided by Entity Framework Core, so our repository will be just a thin layer to hide all the methods from DbSet<User> and the implementation of the specialized repository methods.
  • To materialize the query results we can use the namespace System.Linq to use extension methods such as ToArray(), ToList(), or ToImmutableList() using the namespace System.Collections.Immutable.