Repository Pattern vs DbContext in Entity Framework Core
Tired of arguing about repositories in EF Core? This practical guide compares direct DbContext, thin repositories, and specification style queries with small, runnable C# examples. Learn when each option shines, what to avoid, and how to keep your code clean without hiding EF Core features. We also cover testing pitfalls and safer alternatives. Leave with a simple decision map you can apply to your next .NET project.
If I had a credit for every standup that turned into a heated debate about repositories, I would have enough Azure credits to train a Wookee. Some folks wrap Entity Framework Core in custom repositories. Others inject DbContext straight into services and call it a day. Both camps have good reasons. The trick is knowing when each fit.
In this post we will build a tiny example, compare options, and leave you with a practical checklist so your next data access decision feels like a refactor, not a lightsaber duel.
The baseline: direct DbContext
EF Core already gives you a repository like set and a unit of work in DbContext. That means you can keep things simple and use it directly.
Let’s start with a tiny domain. No midi-chlorians required.
public class Bounty
{
public int Id { get; set; }
public string Hunter { get; set; } = "";
public bool IsCaptured { get; set; }
}
We will store bounties in a DbContext.
public class CantinaContext : DbContext
{
public DbSet<Bounty> Bounties => Set<Bounty>();
public CantinaContext(DbContextOptions<CantinaContext> options)
: base(options) { }
}
Using DbContext directly in a service keeps things lean and easy to read.
public class BountyService
{
private readonly CantinaContext _db;
public BountyService(CantinaContext db) => _db = db;
public Task<List<Bounty>> GetOpenAsync() =>
_db.Bounties.AsNoTracking().Where(b => !b.IsCaptured).ToListAsync();
}