The Repository Pattern

 The Repository Pattern in ASP.NET Core is a design pattern that mediates data access logic and business logic by providing a centralized place to perform data access operations. It abstracts the data layer, allowing the business logic to interact with the data source through a well-defined interface.

Why Use the Repository Pattern

  1. Abstraction: It abstracts the data access code, providing a clean separation between data and business logic.
  2. Testability: It improves testability by allowing you to mock the data access layer.
  3. Maintainability: It centralizes data access logic, making it easier to manage and modify.
  4. Consistency: It ensures consistent data access logic and helps enforce coding standards.

Major Benefits

  1. Separation of Concerns: Keeps data access logic separate from business logic.
  2. Loose Coupling: Reduces dependencies between different parts of the application.
  3. Code Reusability: Encourages reuse of data access logic across multiple services.
  4. Unit Testing: Facilitates unit testing by allowing the data access layer to be mocked.

Example

Here's an example of implementing the Repository Pattern in an ASP.NET Core application.


Step 1: Define the Service Interface

public interface IProductService
{
    Task<IEnumerable<Product>> GetAllProductsAsync();
    Task<Product> GetProductByIdAsync(int id);
    Task CreateProductAsync(Product product);
    Task UpdateProductAsync(Product product);
    Task DeleteProductAsync(int id);
}

Step 2: Implement the Service

public class ProductService : IProductService
{
    private readonly IProductRepository _productRepository;

    public ProductService(IProductRepository productRepository)
    {
        _productRepository = productRepository;
    }

    public async Task<IEnumerable<Product>> GetAllProductsAsync()
    {
        // Business logic can be added here
        return await _productRepository.GetAllAsync();
    }

    public async Task<Product> GetProductByIdAsync(int id)
    {
        // Business logic can be added here
        return await _productRepository.GetByIdAsync(id);
    }

    public async Task CreateProductAsync(Product product)
    {
        // Business logic such as validation can be added here
        await _productRepository.AddAsync(product);
    }

    public async Task UpdateProductAsync(Product product)
    {
        // Business logic such as validation can be added here
        await _productRepository.UpdateAsync(product);
    }

    public async Task DeleteProductAsync(int id)
    {
        // Business logic can be added here
        await _productRepository.DeleteAsync(id);
    }
}

Step 3: Register the Service in the Dependency Injection Container

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

    services.AddScoped<IProductRepository, ProductRepository>();
    services.AddScoped<IProductService, ProductService>();
}

Step 4: Use the Service in the Controller

[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
    private readonly IProductService _productService;

    public ProductsController(IProductService productService)
    {
        _productService = productService;
    }

    [HttpGet]
    public async Task<ActionResult<IEnumerable<Product>>> GetProducts()
    {
        var products = await _productService.GetAllProductsAsync();
        return Ok(products);
    }

    [HttpGet("{id}")]
    public async Task<ActionResult<Product>> GetProduct(int id)
    {
        var product = await _productService.GetProductByIdAsync(id);
        if (product == null)
        {
            return NotFound();
        }
        return Ok(product);
    }

    [HttpPost]
    public async Task<ActionResult> CreateProduct(Product product)
    {
        await _productService.CreateProductAsync(product);
        return CreatedAtAction(nameof(GetProduct), new { id = product.Id }, product);
    }

    [HttpPut("{id}")]
    public async Task<IActionResult> UpdateProduct(int id, Product product)
    {
        if (id != product.Id)
        {
            return BadRequest();
        }
        await _productService.UpdateProductAsync(product);
        return NoContent();
    }

    [HttpDelete("{id}")]
    public async Task<IActionResult> DeleteProduct(int id)
    {
        await _productService.DeleteProductAsync(id);
        return NoContent();
    }
}

Summary

  • Repository: Handles data access logic.
  • Service: Contains business logic and uses the repository for data access.
  • Controller: Interacts with the service to fulfill HTTP requests.

By adding a service layer, you encapsulate business logic within the service, keeping the controller focused on handling HTTP requests and responses. This approach ensures a clean separation of concerns and enhances maintainability and testability.

Vikash Chauhan

C# & .NET experienced Software Engineer with a demonstrated history of working in the computer software industry.

Post a Comment

Previous Post Next Post

Contact Form