Repository Pattern C#

asp.net-mvc, c#

Solution

I'm glad you asked. The easy answer is don't use the repository pattern. The purpose of the repository pattern is to abstract SQL and other low-level data access logic away, and as a result, the pattern is superfluous with ORMs like Entity Framework. In fact, Entity Framework already implements the Unit of Work and Repository patterns: `DbContext` is the UoW and each `DbSet` is a repository.

That doesn't mean that creating an abstraction over your data layer isn't still a good idea, only that that abstraction shouldn't be a repository. You can use the Service Layer pattern or something like the Command Query Responsibility Segregation (CQRS) pattern.

Note: the Service Layer pattern is very different from Microsoft's "service pattern", which directly relates to using (most often SOAP-based) web services.

Problem

I'm still learning programming and at the moment trying to build a little CRUD app for a friend using ASP.NET MVC5. Since I'm doing it mostly for learning the purpose, I'm trying to understand the Repository pattern. At the moment I have a DBContext class for retrieving data using EF and a Repository class that implements a Interface for all my tables. My main question would be should I have a different Repository class for different tables, since it seems my repository class will grow pretty big if I add more methods to it to manipulate DB data and the Interface kinda seems pointless atm if I'm only using 1 repository class. If I have multiple repository classes should I use Dependency Injection to Inject the needed table to the controller that needs it? And if I do so, then how about Delete action - if I want to delete a Worker that has a List of Bonuses and my controller uses the "Worker Repository" how would I delete the Bonuses related to my Worker? I'm still learning and I am trying to "learn right" so I don't have to re-learn later. So any help would be appreciated. ``` public class BonusSystemDbContext : DbContext { public DbSet<Admin> Admins { get; set; } public DbSet<Worker> Workers { get; set; } public DbSet<Position> Positions { get; set; } public DbSet<Bonus> Bonuses { get; set; } } public class BonusSystemRepository : IBonusSystemRepository { private BonusSystemDbContext context = new BonusSystemDbContext(); public IEnumerable<Admin> Admins => context.Admins; public IEnumerable<Bonus> Bonuses => context.Bonuses; public IEnumerable<Position> Positions => context.Positions; public IEnumerable<Worker> Workers => context.Workers; public void SaveBonus(Bonus bonus) { if (bonus.ID == 0) { context.Bonuses.Add(bonus); } else { Bonus dbEntry = context.Bonuses.Find(bonus.ID); if (dbEntry != null) { dbEntry.WorkerID = bonus.WorkerID; dbEntry.Date = bonus.Date; dbEntry.Amount = bonus.Amount; } } context.SaveChanges(); } public void SavePosition(Position position) { if (position.ID == 0) { context.Positions.Add(position); } else { Position dbEntry = context.Positions.Find(position.ID); if (dbEntry != null) { dbEntry.Workers = position.Workers; dbEntry.Name = position.Name; dbEntry.BeginBonusKg = position.BeginBonusKg; dbEntry.CentsPerKg = position.CentsPerKg; } } context.SaveChanges(); } public void SaveWorker(Worker worker) { if (worker.ID == 0) { context.Workers.Add(worker); } else { Worker dbEntry = context.Workers.Find(worker.ID); if (dbEntry != null) { dbEntry.FirstName = worker.FirstName; dbEntry.LastName = worker.LastName; dbEntry.Position = worker.Position; dbEntry.PositionID = worker.PositionID; dbEntry.Bonuses = worker.Bonuses; dbEntry.HealthCertificate = worker.HealthCertificate; dbEntry.WorkHealthCare = worker.WorkHealthCare; } } context.SaveChanges(); } } public interface IBonusSystemRepository { IEnumerable<Admin> Admins { get; } IEnumerable<Bonus> Bonuses { get; } IEnumerable<Position> Positions { get; } IEnumerable<Worker> Workers { get; } void SaveBonus(Bonus bonus); void SavePosition(Position position); void SaveWorker(Worker worker); } ``` And my db sample Table objects: ``` public class Worker { [Key] public int ID { get; set; } [ForeignKey("Position")] public int PositionID { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public DateTime? WorkHealthCare { get; set; } public DateTime? HealthCertificate { get; set; } public virtual Position Position { get; set; } public virtual ICollection<Bonus> Bonuses { get; set; } } public class Bonus { [Key] public int ID { get; set; } [ForeignKey("Worker")] public int WorkerID { get; set; } public DateTime? Date { get; set; } public decimal Amount { get; set; } public virtual Worker Worker { get; set; } } ```

Original source