Back to all posts
·5 min read

Repository Pattern in .NET: A No-Nonsense Guide

Let's cut through the jargon and talk about the Repository Pattern like real people. Think of it as creating a middleman between your business logic and your database—one that actually makes your life easier.

.NETC#Design PatternsClean CodeArchitecture

Repository Pattern in .NET: A No-Nonsense Guide

Let's cut through the jargon and talk about the Repository Pattern like real people. Think of it as creating a middleman between your business logic and your database—one that actually makes your life easier.

Why Should You Care?

Picture this: You're building an app, and your database code is everywhere. Tomorrow, your boss says "Let's switch from SQL Server to MongoDB." You'd probably want to cry, right? That's where the Repository Pattern saves you.

In plain English: It's a layer that sits between your app and your database, so you can swap out data sources without rewriting half your codebase.

The Real-World Example

Let's say you're building a simple blog. You need to save and retrieve posts. Here's how most people start:

// ❌ The "I'll regret this later" approach
public class BlogService
{
    private readonly DbContext _db;

    public BlogPost GetPost(int id)
    {
        return _db.BlogPosts.FirstOrDefault(p => p.Id == id);
    }
}

This works, but now your BlogService is married to Entity Framework. Good luck testing this or switching databases.

Enter the Repository Pattern

Here's the smarter way:

Step 1: Define What You Need (The Interface)

public interface IBlogRepository
{
    BlogPost GetById(int id);
    IEnumerable<BlogPost> GetAll();
    void Add(BlogPost post);
    void Update(BlogPost post);
    void Delete(int id);
}

This is your contract. Notice how it says nothing about databases? That's intentional.

Step 2: Implement It (The Actual Repository)

public class BlogRepository : IBlogRepository
{
    private readonly ApplicationDbContext _context;

    public BlogRepository(ApplicationDbContext context)
    {
        _context = context;
    }

    public BlogPost GetById(int id)
    {
        return _context.BlogPosts.FirstOrDefault(p => p.Id == id);
    }

    public IEnumerable<BlogPost> GetAll()
    {
        return _context.BlogPosts.ToList();
    }

    public void Add(BlogPost post)
    {
        _context.BlogPosts.Add(post);
        _context.SaveChanges();
    }

    public void Update(BlogPost post)
    {
        _context.BlogPosts.Update(post);
        _context.SaveChanges();
    }

    public void Delete(int id)
    {
        var post = GetById(id);
        if (post != null)
        {
            _context.BlogPosts.Remove(post);
            _context.SaveChanges();
        }
    }
}

Step 3: Use It in Your Service

public class BlogService
{
    private readonly IBlogRepository _repository;

    public BlogService(IBlogRepository repository)
    {
        _repository = repository;
    }

    public BlogPost GetPost(int id)
    {
        return _repository.GetById(id);
    }

    public void PublishPost(BlogPost post)
    {
        post.PublishedAt = DateTime.Now;
        _repository.Add(post);
    }
}

Step 4: Wire It Up (Dependency Injection)

In your Program.cs:

builder.Services.AddScoped<IBlogRepository, BlogRepository>();
builder.Services.AddScoped<BlogService>();

What Just Happened?

Your BlogService now has zero clue about Entity Framework or databases. It just knows it can ask for posts and save them.

Want to switch to Dapper? MongoDB? A JSON file? Just create a new implementation of IBlogRepository. Your service code stays untouched.

The Real Benefits

  1. Testing becomes a breeze - Mock IBlogRepository and test your business logic without touching a database
  2. Flexibility - Swap data sources without rewriting your entire app
  3. Cleaner code - Each class has one job and does it well
  4. Team sanity - Your teammates won't hate you when they have to maintain this later

When NOT to Use It

Real talk: If you're building a tiny CRUD app with 3 tables, this might be overkill. Don't over-engineer. But if your app is growing or you know it will, the Repository Pattern is your friend.

The Bottom Line

The Repository Pattern isn't magic—it's just good organization. You're drawing a clear line between "how we store data" and "what we do with data."

Future you (and your teammates) will thank present you for making this choice.


Questions or war stories about using the Repository Pattern? I'd love to hear them. Hit me up!


This article was reviewed and improved using AI.

F
Fernando Callata

© 2026. Excellence in first place.