DbContext Dependency Injection outside of MVC project

只谈情不闲聊 提交于 2019-12-06 00:36:46

You don't need to pass context to controller to be able to use the context registered in services inside repository. The way I prefer to do that, is the following. Inject context into repository and then inject repository into controller. Using the Microsoft Dependency Injection Extension in for .Net Core it will look like this

// Service registrations in Startup class
public void ConfigureServices(IServiceCollection services)
{
    // Also other service registrations
    services.AddMvc();
    services.AddScoped<DatabaseContext, DatabaseContext>();
    services.AddScoped<ICustomerRepository<Customer>, CustomerRepository>();
}

// Controller
namespace ProductStore.Web.Controllers
{
    public class HomeController : Controller
    {
        private readonly ICustomerRepository _customerRepository;

        public HomeController(ICustomerRepository customerRepository)
        {
            _customerRepository = customerRepository;
        }
        public IActionResult Index()
        {
            Customer customer = new Customer
            {
                // customer details
            };
            //_context.Customers.Add(customer);
            int result = _customerRepository.Create(customer).Result;
            return View();
        }
    }
}

//Repository
namespace ProductStore.Data
{
    public class CustomerRepository : ICustomerRepository<Customer>
    {
        DatabaseContext _context;
        public CustomerRepository(DatabaseContext context)
        {
            _context = context;
        }
    }
}

After this when DependencyResolver tries to resolve ICustomerRepository to inject into the HomeController he sees, that the registered implementation of ICustomerRepository (in our case CustomerRepository) has one constructor which needs DatabaseContext as a parameter and DependencyResolver trying to to get registered service for DatabaseContext and inject it into CustomerRepository

If you define your repository in your ConfigureServices method, you won't need to inject the DbContext into controller, just the repository:

public void ConfigureServices(IServiceCollection services)
{
  services.AddDbContext<DbContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
        
  services.AddScoped(typeof(ICustomerRepository<>), typeof(CustomerRepository<>));
}

Then you can just simply inject the repository into controller:

public class HomeController : Controller
{
  private readonly ICustomerRepository _customerRepository;

  public HomeController(ICustomerRepository customerRepository)
  {
      _customerRepository = customerRepository;
  }
  ...
}

The dependency injector takes care of injecting DbContext into your repository.

1. Is this best practice (passing the context from controller to CustomerRepository)

I think you're looking for something like a "Unit of Work" pattern.

Microsoft has written a tutorial about creating one here.

I would also inject the repository in your controller instead of your context.

2. If not best practice, can I access context via IServiceCollection services in a similar way to how the DatabaseContext is inserted into services in my application StartUp.cs class...

If I understand you correctly, than yes, you can. Also add the CustomerRepository to the services in your StartUp.cs so you can use it in your controller.

Mabye this tutorial from Microsoft will also help you.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!