C#.NET - day 04
Source: Dev.to
Step 1.5 : Introducing the Repository Pattern
Separating responsibilities to build systems that scale
Introduction
The core idea of this step is perfect separation of roles.
Instead of putting everything into one place, we clearly divide responsibilities so that each part of the system focuses on a single concern.
This step may feel subtle, but once it clicks, many architectural decisions in C# and enterprise systems start to make sense.
The Structural Upgrade
Before
- Service handled both business logic and data storage
- Controller called the Service directly
Pro Version
- Repository → responsible only for storage
- Service → responsible only for business logic
- Controller → responsible only for request handling
In short:
Controller → Service → Repository
🌊 Flow: Upgraded System Behavior
- Controller receives the user’s name and forwards it to the Service.
- Service creates the business card (business logic) and tells the Repository to store it.
- Repository stores the data without asking questions.
1️⃣ Step 1: Hiring a Storekeeper (Repository)
Create a new folder named Repositories, then add a class called HelloRepository.
using HelloFlow.Models;
namespace HelloFlow.Repositories;
public class HelloRepository
{
private readonly List _storage = new();
public void Save(HelloResponse data)
{
_storage.Add(data);
}
public List GetAll()
{
return _storage;
}
}
This class does exactly two things:
- Save data
- Return stored data
No logic. No interpretation. Just storage.
2️⃣ Step 2: Reducing the Chef’s Duties (Service)
Open Services/HelloService.cs and update it as follows:
using HelloFlow.Models;
using HelloFlow.Repositories;
namespace HelloFlow.Services;
public class HelloService
{
private readonly HelloRepository _repository;
public HelloService(HelloRepository repository)
{
_repository = repository;
}
public HelloResponse GetHello(string name)
{
var response = new HelloResponse
{
Message = $"Hello, {name}! (Repository Version)",
CreatedAt = DateTime.Now,
Location = "Cazis, Switzerland"
};
_repository.Save(response);
return response;
}
public List GetHistory()
{
return _repository.GetAll();
}
}
Key shift: The Service no longer knows where data is stored.
3️⃣ Step 3: Organizational Changes (Program.cs)
Register the new role in the DI container.
using HelloFlow.Services;
using HelloFlow.Repositories;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// Repository: Singleton (keeps memory)
builder.Services.AddSingleton();
// Service: Scoped (stateless worker)
builder.Services.AddScoped();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.MapControllers();
app.Run();
This configuration makes responsibilities explicit and predictable.
🧠 Why This Version Is “Deep”
When you replace in‑memory storage with a real database:
- The Service does not change
- The Controller does not change
- Only the Repository changes
This is the practical meaning of Separation of Concerns.
🧠 One‑Sentence Summary
The person who cooks (Service) and the person who stores ingredients (Repository) are now completely separated.
What to Remember at This Stage
- Repository handles storage only
- Service handles business logic only
- Controller handles requests only
Program.cs decides who works with whom.
✍️ My Notes & Reflections
- I feel that I have started to understand what a Singleton is. I am not fully confident yet, but this step made its purpose much clearer.
- It also made me think that C# is a language where clearly separating responsibilities between different components is especially important.