简体   繁体   中英

Ramifications of using DBContext with Dependency Injection

I'm still kind of new to using dependency injection to manage my DBContext in an ASP.NET MVC application I'm writing.

I'm attempting to follow the approach outlined in the article Managing Entity Framework DbContext Lifetime in ASP.NET MVC . Basically, this approach says to use Ninject and dependency injection and to add my DBContext as a parameter to the constructor in my controllers.

Further, I am implementing this in a base controller, or which all my controller classes will be derived.

This is working, but I'm hitting on the following issues.

  1. This approach requires that every derived controller class also implements a constructor that accepts any arguments requires by my controller base class. Not only does this seem like a lot of extra typing that I must remember to add to any new derived class, but it also means that if I change the data passed to the constructor then I must modify the constructor in every derived controller class.

  2. This gives me a DBContext for all my controller classes. But what about other classes in my model that need the DBContext? Should I need to manually pass the instance to the DBContext to all these classes? Or is there a way to use DI for each of these classes to get their own copy of the DBContext?

This approach requires that every derived controller class also implements a constructor that accepts any arguments requires by my controller base class. Not only does this seem like a lot of extra typing that I must remember to add to any new derived class, but it also means that if I change the data passed to the constructor then I must modify the constructor in every derived controller class.

This is one of the approach (Heavy Controller) that you may choose to use EF into your application, IMO its not the cleanest approach. And you correctly noticed the drawbacks your self.

If we relate this approach to design principle, it breaks Single Responsibility Principle as controller is expected to do more (fetch or update DB) than just collecting the data and return the appropriate view with data. And how about business rules, would controller apply it, if you need to send an email, would controller does that as well. You ought to have another layer of business/service classes that are specifically designed for a set of requirement eg EmailHelper would send emails.

It also breaks Open Close Principle as you need to change the constructors every time you change the input parameter.

This gives me a DBContext for all my controller classes. But what about other classes in my model that need the DBContext? Should I need to manually pass the instance to the DBContext to all these classes?

As far as dependency injection is concerned one of the goal is, to inject the dependency where it is needed directly. If you have a model class that needs DbContext, you should inject it in your model class constructor (most DI framework support property injection as well but constructor remains favourite approach).

With DI Framework, you will configure the dependencies at one place (application initialization code) and then each class that need a dependency just accept it in constructor.

DI Container can be compared to a dictionary where key is interface and the value is a cooked object. Once its setup, you can anytime ask for any object by using the right key through out your application.

Or is there a way to use DI for each of these classes to get their own copy of the DBContext?

The DI framework supports different ways of instantiation to allow controlling the lifetime of the instance. Typically, per request, per thread and singleton. More information here . If you want each controller to get a copy of DbContext, you can use per request configuration when you set up DbContext instantiation.

Alternate Solution:

Most of my MVC applications, I have had a service layer (set of classes that apply business rule). Each of these classes were injected with DbContext (not exactly a DbContext but IDataContext). The controllers were injected with the service class that they need to retrieve or update the data.

Have abstracted the DbContext behind IDataContext, I could setup a stub data context in my test or tomorrow if I want to switch from EF to NHibernate or something more smart DI Framework, i will just have to implement IDataContext and change the dependency initialization code.

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM