C#
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Object-Oriented C#
-
Section 4: Working with Data
-
Section 5: Error Handling
-
Section 6: Delegates and Events
-
Section 7: Async Programming
-
Section 8: More Language Features
-
Section 9: File I/O and Serialization
-
Section 10: Networking in .NET
-
Section 11: The .NET Ecosystem
-
Section 12: Memory and Performance
-
Section 13: Concurrency Beyond Async
-
Section 14: Reflection and Attributes
-
Section 15: Testing and Best Practices
-
Section 16: Design Patterns in C#
-
Section 17: Standard Library Deep Dive
-
Section 18: Data Structures and Algorithms in C#
-
Section 19: GUI and Desktop Development Overview
-
Section 20: Practical Projects
-
Section 21: More Practice Exercises
-
Section 22: More Standard Library and Text Processing
-
Section 23: More Design Patterns
-
Section 24: More Projects
-
Section 25: Interview Practice
-
Section 26: C# Keywords Reference (Modifiers)
-
Section 27: C# Keywords Reference (Statements)
-
Section 28: C# Keywords Reference (Operators)
-
Section 29: BCL: System.Collections.Generic
-
Section 30: BCL: System.Linq
-
Section 31: BCL: System.Threading
-
Section 32: BCL: System.IO
-
Section 33: BCL: System.Text and System.Text.Json
-
Section 34: BCL: System.Net.Http
-
Section 35: C# Language Specification Topics
-
Section 36: More Practice Exercises
-
Section 37: More Async Patterns
-
Section 38: More BCL: System.Reflection and System.Diagnostics
-
Section 39: Nullable Reference Types In Depth
-
Section 40: C# Records and Pattern Matching In Depth
-
Section 41: Dependency Injection Deep Dive
-
Section 42: More Interview and Whiteboard Practice
106: The Repository Pattern
Imagine you're at a massive public library. You need a specific book on C# design patterns. You don't just wander into the basement, start climbing ladders, and manually searching through thousands of Dewey Decimal codes to find the physical shelf where that book sits. That would be a nightmare, and if the library reorganized its shelves tomorrow, you'd be totally lost.
Instead, you go to the librarian. You say, "I need the book on design patterns," and the librarian handles the rest. You don't care if they use a computer, a handwritten ledger, or their own memory to find it. You just want the book. The librarian acts as the mediator between you and the chaotic reality of the bookshelves.
In C#, the Repository Pattern is exactly that librarian. Your business logic (the user) asks for data, and the repository (the librarian) handles the gritty details of how to fetch it from the database (the bookshelves).
Defining the Contract
The secret to making this work is starting with an interface. If we just create a class that talks to a database, we've just moved the mess to a different file. We want an abstraction. Let's say we're building a system to manage a collection of Game objects for a digital storefront.
public interface IGameRepository
{
Game GetById(int id);
IEnumerable<Game> GetAll();
void Add(Game game);
void Delete(int id);
}
Notice how there is absolutely nothing in here about SQL, Entity Framework, or JSON files. This is the "contract." Any part of your app that needs a game just talks to this interface. It doesn't know—or care—where the games are actually stored.
Hiding the EF Core Mess
Now we actually build the librarian. This is where the "how" happens. I'll use Entity Framework Core here because that's what most of us use, but the beauty is that the rest of your app won't know that.
public class SqlGameRepository : IGameRepository
{
private readonly GameDbContext _context;
public SqlGameRepository(GameDbContext context)
{
_context = context;
}
public Game GetById(int id) => _context.Games.Find(id);
public IEnumerable<Game> GetAll() => _context.Games.ToList();
public void Add(Game game)
{
_context.Games.Add(game);
_context.SaveChanges();
}
public void Delete(int id)
{
var game = _context.Games.Find(id);
if (game != null)
{
_context.Games.Remove(game);
_context.SaveChanges();
}
}
}
I've seen a lot of developers argue that this is "boilerplate" because EF Core's DbSet is already a kind of repository. And they're not entirely wrong. But once you start adding complex filters or custom logic to your queries, your controllers start getting bloated with LINQ expressions. By wrapping this in a repository, you keep that logic in one place.
Why We Actually Bother With This
You might be thinking, "This feels like extra work for no reason." Here is where it pays off: Unit Testing.
If your business logic is hard-coded to use SqlGameRepository, you can't test your logic without a real database running. That's slow and flaky. But because we used IGameRepository, you can create a "Mock" repository in your tests—basically a fake librarian who just returns a list of games from memory. Your tests will run in milliseconds, and you won't have to clean up a database after every run.
Another win? Imagine your boss comes to you in six months and says, "We're moving our game data from SQL Server to MongoDB." If you've used the Repository Pattern, you don't have to touch a single line of code in your business services. You just write a new MongoGameRepository that implements the same interface, swap the registration in your Dependency Injection container, and you're done.
📋 Practical Task
Refactoring the Product Catalog Storage
You've inherited a project for an e-commerce site. Currently, the ProductService class is "fat"—it's directly using a DbContext to perform database queries, making it impossible to unit test without a live database connection.
Your Task:
- Create an interface named
IProductRepositorythat defines methods forGetProductById(int id),GetProductsByCategory(string category), andUpdateStock(int id, int newQuantity). - Implement this interface in a class called
SqlProductRepository. Assume you have aProductDbContextavailable with aDbSet<Product>. - Modify the
ProductServiceclass to acceptIProductRepositoryvia its constructor instead of theProductDbContext. - Update the methods in
ProductServiceto call the repository methods instead of querying the context directly.
There are no comments for now.