Repository Pattern in NET 9: Benefits and Professional Application

16 de September 2025

Imagine developing a .NET 9.0 application where business logic is completely intertwined with data access logic. Every change in the database forces modifications to multiple parts of the code. This is a recipe for chaos.

This is where the Repository Pattern comes in—an architectural strategy that not only organizes your code but also improves its maintainability, scalability, and testability. In this article, you’ll learn what it is, how to implement it in .NET 9.0, and why it can be key in your enterprise projects.

What is the Repository Pattern?

The Repository Pattern acts as an intermediate layer between the business logic and the data source. Its main function is to abstract data access, allowing the business code to remain clean and focused on its primary responsibility.

Key Benefits:

  • Decoupling between business logic and persistence.
  • Easy to test using mocks or fakes.
  • Reusability of data access code.
  • Changing data providers without modifying the business layer.

Advantages of a Generic Repository

A generic repository allows you to define a single, reusable implementation for any entity in your domain model, offering additional benefits:

  • Reduced duplicate code: You don’t need to write the same basic CRUD for each entity.
  • Consistency: All operations follow a unified structure, facilitating maintenance and refactoring.
  • Flexibility: You can extend or override it in specific repositories when necessary.
  • Scalability: Ideal for large projects with many similar entities.

Layered Architecture: Who Calls Whom

A request flows through the application in this way:

  1. Client (e.g., Angular frontend or Postman)
  2. Controller: receives the HTTP request.
  3. Service: contains the business logic.
  4. Repository: communicates with the database.
  5. Database: stores or retrieves data.

Each layer only interacts with the immediately lower layer, promoting a clean and maintainable architecture.

Implementing the Repository Pattern in .NET 9.0

1. Domain Model

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; } = string.Empty;
    public decimal Price { get; set; }
}

2. Generic Repository Interface

public interface IRepository<T> where T : class
{
    Task<IEnumerable<T>> GetAllAsync();
    Task<T?> GetByIdAsync(int id);
    Task AddAsync(T entity);
    Task UpdateAsync(T entity);
    Task DeleteAsync(int id);
}

3. Generic Repository Implementation

public class Repository<T> : IRepository<T> where T : class
{
    private readonly DbContext _context;
    private readonly DbSet<T> _dbSet;

    public Repository(DbContext context)
    {
        _context = context;
        _dbSet = context.Set<T>();
    }

    public async Task<IEnumerable<T>> GetAllAsync() => await _dbSet.ToListAsync();

    public async Task<T?> GetByIdAsync(int id) => await _dbSet.FindAsync(id);

    public async Task AddAsync(T entity)
    {
        await _dbSet.AddAsync(entity);
        await _context.SaveChangesAsync();
    }

    public async Task UpdateAsync(T entity)
    {
        _dbSet.Update(entity);
        await _context.SaveChangesAsync();
    }

    public async Task DeleteAsync(int id)
    {
        var entity = await GetByIdAsync(id);
        if (entity != null)
        {
            _dbSet.Remove(entity);
            await _context.SaveChangesAsync();
        }
    }
}

4. Business Service

public class ProductService
{
    private readonly IRepository<Product> _repository;

    public ProductService(IRepository<Product> repository)
    {
        _repository = repository;
    }

    public async Task CreateProductAsync(Product product)
    {
        if (product.Price <= 0)
            throw new ArgumentException("Price must be greater than zero");

        await _repository.AddAsync(product);
    }
}

5. Dependency Injection in Program.cs

builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("Default")));

builder.Services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
builder.Services.AddScoped<ProductService>();

Comparison: Generic Repository vs Specific Repository

FeatureGeneric RepositorySpecific Repository
Reusable CodeHigh: a single implementation serves multiple entities.Low: one is written per entity.
Ease of MaintenanceHigh: changes in generic logic affect all entities.Medium: each change must be done separately.
Initial ComplexityLow: easy to implement for basic operations.High: requires more initial code.
Flexibility for Complex QueriesLimited: not ideal for custom queries.High: allows adapting logic to specific needs.
ScalabilityExcellent for many similar entities.Suitable for entities with very different rules.

Export to Sheets

Recommendation: Use a generic repository for common CRUD operations and complement it with specific repositories when you need specialized queries or entity-dependent business logic.

Best Practices

  • Do not put business logic in the repository. Keep it in the services.
  • Use interfaces to facilitate testing. You can use libraries like Moq to simulate the data layer.
  • Add specific repositories only if the entity has complex queries.

Conclusion

The Repository Pattern in .NET 9.0 is much more than an organizational technique: it is an architectural strategy that allows you to build more professional, scalable, and maintainable solutions.

Whether you are creating a small module or an enterprise platform, this pattern can help you deliver more robust and future-proof solutions.

Do you want to implement this pattern in your next project? Contact us and we will help you design a clean and effective architecture from the start.

//Technologies we excel in

ingenius_technologies
ingenius_technologies
ingenius_technologies
ingenius_technologies
ingenius_technologies
ingenius_technologies
ingenius_technologies
ingenius_technologies
ingenius_technologies
ingenius_technologies
ingenius_technologies
ingenius_technologies
ingenius_technologies
ingenius_technologies
ingenius_technologies
ingenius_technologies
ingenius_technologies
ingenius_technologies
ingenius_technologies
ingenius_technologies
ingenius_technologies

// WHO TRUSTS US

ingenius_cliente
ingenius_cliente
ingenius_cliente
ingenius_cliente
ingenius_cliente
ingenius_cliente

Contact us today

Let's talk about how we can help you transform your business through innovative software solutions.