Our previous article Repository Pattern, Unit Of Work with EF Core and Dapper discussed the Repository Pattern and its implementation using Entity Framework Core and Dapper. In this article, we introduce an enhanced version of the pattern that increases flexibility and robustness in your data access layer.
In the original Repository Pattern, we often dealt with specific entity types and their corresponding primary keys - usually named ‘Id’. However, maintaining separate repositories for each entity type becomes cumbersome as the application grows. How can we make the handling of primary keys more general?
We introduce a new concept - the generic Id - which allows us to handle various entity types seamlessly. Instead of relying on a specific type for the primary key, we use a generic type parameter.
public interface IRepository<TEntity, TId>
{
TEntity Get(TId id);
ValueTask<TEntity> GetAsync(TId id, CancellationToken cancellationToken);
...
and it’s implementations:
public virtual TEntity Get(TId id)
=> _context.Set<TEntity>().Find(id);
public virtual async ValueTask<TEntity> GetAsync(TId id, CancellationToken cancellationToken)
=> await _context.Set<TEntity>().FindAsync(new object[] { id }, cancellationToken);
public TEntity Get(TId id)
=> _connection.Get<TEntity, TId>(id);
public async ValueTask<TEntity> GetAsync(TId id, CancellationToken cancellationToken)
=> await _connection.GetAsync<TEntity, TId>(id, cancellationToken);
You can find the code on my GitHub profile by clicking on the following link: ATech.Repository. The repository also includes a continuous integration and continuous deployment workflow, which is implemented using GitHub Actions. As a result of this workflow, three NuGet packages are created and published, which are available at https://www.nuget.org/packages?q=ATech.Repository.
Enjoy,