How to design a Repository Pattern with Dependency Injection in ASP.NET Core MVC?

Giancarlo Sierra picture Giancarlo Sierra · Feb 21, 2017 · Viewed 35.2k times · Source

Being fairly new to ASP.NET Core 1.0 MVC, I have decided to use a Repository Pattern for an MVC Core app; I'm using a SQL DB for the Data Layer SampleDbContext, and I want to have a Repository class for some of my business Entities. So far I have done the following in thestartup.cs, CustomerController.cs and CustomerRepository.cs files, where a sample Entity is "Customer".

In the ConfigureServices method of the Startup Class:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<SampleDbContext>(options =>
       options.UseSqlServer(Configuration.GetConnectionString("SampleDB")));
}

In a Controller:

public class CustomerController : Controller
{

    private SampleDBContext _context;
    private CustomerRepository = new CustomerRepository (new SampleDBContext());

    public CustomerController(SampleDBContext context)
    {
        _context = context;
    }
}

In a Repository:

public class CustomerRepository
{
    private SampleDBContext _context;

    public CustomerRepository(SampleDBContext context)
    {
        _context = context;
    }
}

With this design, I plug in the SampleDbContext as a service in the startup.cs once, and then for each Controller (that receives Dependency Injection) I instantiate a corresponding Repository passing along a new instance of the SampleDbContext. Is this repetitive instantiation of the DB context a good design for a multi-user environment? I suppose I could add each Repository as a service to the startup.cs but that doesn't look nice. Please tell me a good design implementation for my case, or put me in the right track if I'm lost.

Answer

Alexan picture Alexan · Feb 21, 2017

You can see simple example how to use repository pattern:

You create repository interface:

using System.Collections.Generic;

namespace TodoApi.Models
{
    public interface ITodoRepository
    {
        void Add(TodoItem item);
        IEnumerable<TodoItem> GetAll();
        TodoItem Find(long key);
        void Remove(long key);
        void Update(TodoItem item);
    }
}

Then implement it:

using System;
using System.Collections.Generic;
using System.Linq;

namespace TodoApi.Models
{
    public class TodoRepository : ITodoRepository
    {
        private readonly TodoContext _context;

        public TodoRepository(TodoContext context)
        {
            _context = context;
            Add(new TodoItem { Name = "Item1" });
        }

        public IEnumerable<TodoItem> GetAll()
        {
            return _context.TodoItems.ToList();
        }

        public void Add(TodoItem item)
        {
            _context.TodoItems.Add(item);
            _context.SaveChanges();
        }

        public TodoItem Find(long key)
        {
            return _context.TodoItems.FirstOrDefault(t => t.Key == key);
        }

        public void Remove(long key)
        {
            var entity = _context.TodoItems.First(t => t.Key == key);
            _context.TodoItems.Remove(entity);
            _context.SaveChanges();
        }

        public void Update(TodoItem item)
        {
            _context.TodoItems.Update(item);
            _context.SaveChanges();
        }
    }
}

Then register in ConfigureServices:

services.AddSingleton<ITodoRepository, TodoRepository>();

Then inject it to Controller:

namespace TodoApi.Controllers
{
    [Route("api/[controller]")]
    public class TodoController : Controller
    {
        public TodoController(ITodoRepository todoItems)
        {
            TodoItems = todoItems;
        }
        public ITodoRepository TodoItems { get; set; }
    }
}