Stenehr
Stenehr

Reputation: 86

Repository Pattern C#

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; }
}

Upvotes: 6

Views: 803

Answers (1)

Chris Pratt
Chris Pratt

Reputation: 239290

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.

Upvotes: 6

Related Questions