In previous article, We have implemented Application Layer in Clean Architecture, if you have not visited then requesting to vist and continue this post . Here in this article, we will explore the implementation of Infracture Layer
The Infrastructure Layer handles the technical implementation of external dependencies, such as database access and data persistence. It provides concrete implementations of the interfaces defined in the Application Layer.
In our Employee Management application, we will use Entity Framework Core to interact with SQL Server. We will create a database context, configure entity mappings, and implement the employee repository to perform CRUD operations. We will also configure dependency injection to register the infrastructure services.
ASP. NET Clean Architecture: Implementing Infrastructure Layer in Web API
Getting Started
The Infrastructure Layer is responsible for implementing the technical details required by the application, such as database access, repository implementations, external API integrations, file storage, and other infrastructure-related operations.
In our Employee Management Web API, we will use Entity Framework Core with SQL Server to manage employee data.
In the previous section, we created the IEmployeeRepository interface in the Application Layer. Now, we will implement this interface in the Infrastructure Layer to perform database operations.
Let's implement the Infrastructure Layer step by step.Step 1: Create the Folder Structure
Create the following folders:</> Plain Text
CleanArchitectureDemo.Infrastructure
│
├── Data
│
└── Repositories
Each folder has a specific responsibility:
- Data: Contains database context and database configurations.
- Repositories: Contains repository implementations.
Step 2: Install Entity Framework Core Packages
Open the Package Manager Console and select Infrastructure as the default project.
</> powershell
Install-Package Microsoft.EntityFrameworkCore
Install-Package Microsoft.EntityFrameworkCore.SqlServer
Install-Package Microsoft.EntityFrameworkCore.Design
Step 3: Create the ApplicationDbContext
The DbContext class represents a session with the database and provides access to the entities managed by Entity Framework Core. Inside the Data folder, create a class named ApplicationDbContext.cs.
</> C#
using CleanArchitectureDemo.Domain.Entities;
using Microsoft.EntityFrameworkCore;
namespace CleanArchitectureDemo.Infrastructure.Data;
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext(
DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
public DbSet<Employee> Employees => Set<Employee>();
protected override void OnModelCreating(
ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Employee>(entity =>
{
entity.HasKey(e => e.Id);
entity.Property(e => e.Name)
.IsRequired()
.HasMaxLength(100);
entity.Property(e => e.Email)
.IsRequired()
.HasMaxLength(150);
entity.Property(e => e.Salary)
.HasPrecision(18, 2);
});
}
}
Step 4: Implement the Employee Repository
In the Application Layer, we previously defined the IEmployeeRepository interface. Now, we will implement that interface in the Infrastructure Layer.
EmployeeRepository.cs inside the Repositories folder:
</> C#
using CleanArchitectureDemo.Application.Interfaces;
using CleanArchitectureDemo.Domain.Entities;
using CleanArchitectureDemo.Infrastructure.Data;
using Microsoft.EntityFrameworkCore;
namespace CleanArchitectureDemo.Infrastructure.Repositories
{
public class EmployeeRepository : IEmployeeRepository
{
private readonly ApplicationDbContext _context;
public EmployeeRepository(ApplicationDbContext context)
{
_context = context;
}
public async Task<IEnumerable<Employee>> GetAllAsync()
{
return await _context.Employees.ToListAsync();
}
public async Task<Employee?> GetByIdAsync(int id)
{
return await _context.Employees
.FirstOrDefaultAsync(e => e.Id == id);
}
public async Task AddAsync(Employee employee)
{
await _context.Employees.AddAsync(employee);
await _context.SaveChangesAsync();
}
public async Task UpdateAsync(Employee employee)
{
_context.Employees.Update(employee);
await _context.SaveChangesAsync();
}
public async Task DeleteAsync(Employee employee)
{
_context.Employees.Remove(employee);
await _context.SaveChangesAsync();
}
}
Step 5: Configure Dependency Injection
Next, create DependencyInjection.cs in the root of the Infrastructure project. This class registers the database context and repository implementation with the dependency injection container.
</> C#
using CleanArchitectureDemo.Application.Interfaces;
using CleanArchitectureDemo.Infrastructure.Data;
using CleanArchitectureDemo.Infrastructure.Repositories;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace CleanArchitectureDemo.Infrastructure
{
public static class DependencyInjection
{
public static IServiceCollection AddInfrastructure(
this IServiceCollection services,
IConfiguration configuration)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer( configuration.GetConnectionString("DefaultConnection")));
services.AddScoped<IEmployeeRepository, EmployeeRepository>();
return services;
}
}
}
After completing these steps, our Infrastructure Layer is responsible for:
- Managing database connections through Entity Framework Core.
- Mapping domain entities to database tables.
- Implementing repository interfaces defined in the Application Layer.
- Performing database CRUD operations.
- Registering infrastructure services using dependency injection.
In the next step, we will implement the Presentation Layer, where we create ASP.NET Core Web API controllers, expose RESTful endpoints, handle HTTP requests and responses, and connect the API with the Application Layer of our Employee Management application.
Summary
With the Infrastructure Layer implemented, we have connected our application to the database and provided the necessary implementations for data persistence. It handles the technical details of database communication while keeping the core application logic independent of database-specific technologies. This separation allows us to change or extend infrastructure components without significantly affecting the other layers of our application.
Thanks