In Enterprise .NET, the Repository Pattern abstracts data access logic behind an interface, while the Unit of Work ensures that multiple repository operations use a single database transaction. Together, they create a clean layer of separation between your Business Logic and your Database Technology.
A repository should make the caller feel like they are interacting with a simple List<T>, hidden the complexities of SQL, IQueryable, and DB contexts.
public interface IRepository<T>
{
Task<IEnumerable<T>> GetAll();
void Add(T entity);
}
If you create a 'User' and its 'Settings' in two separate repositories, you want them both to succeed or both to fail. The Unit of Work holds the _context.SaveChangesAsync() method, ensuring atomicity.
public class UnitOfWork : IUnitOfWork
{
private readonly AppDbContext _db;
public IUserRepository Users { get; }
public async Task Complete() => await _db.SaveChangesAsync();
}
Q: "Is it redundant to use the Repository pattern with Entity Framework Core, since DbContext is already a Unit of Work?"
Architect Answer: "Technically, yes. `DbSet` is a Generic Repository and `DbContext` is a Unit of Work. However, we still use repositories to **Decouple** our business logic from EF-specific code. By using a custom repository, we can prevent 'Leaky Abstractions' like exposing `IQueryable` (which allows logic to bleed into the UI layer) and we make our business services much easier to Unit Test without needing a complex InMemory database setup."