ASP.NET Core: Injecting your DB Context into your Controllers

What is Dependancy Injection?

The type of Dependency Injection ill be looking at today can be categorized as “Constructor Injection”.  The idea is that we will inject the needed classes into the constructor, rather than creating or instantiating new objects, thus achieving loose coupling between objects.

When classes are designed with DI in mind, they are more loosely coupled because they do not have direct, hard-coded dependencies on their collaborators. This follows the Dependency Inversion Principle, which states that “high level modules should not depend on low level modules; both should depend on abstractions.” Instead of referencing specific implementations, classes request abstractions (typically interfaces) which are provided to them when the class is constructed. Extracting dependencies into interfaces and providing implementations of these interfaces as parameters is also an example of the Strategy design pattern.
– MS Docs

Dependency Injection is setup in the ConfigureServices method of Startup.cs
This ConfigureServices method is responsible for setting the things that can be injected into our constructors.

Each services.Add extension method adds (and potentially configures) services. For example, services.AddMvc() adds the services MVC requires.
– MS Docs

In this example I will focus on setting up DB Contexts. To learn more about registering your own services check out Microsoft’s docs here.


Creating a New ASP.NET Core Web Application

When you create a new ASP.NET Core Web Application with Authentication your ConfigureServices method and appsetting.json are set up automatically for you. This is a good place to start. You will see that AddDBContext() is in ConfigureServices and the connection string is stored in appsettings.json.  It should look something like this…

        public void ConfigureServices(IServiceCollection services)
        {
            // Add framework services.
            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

            .................
        }
appsettings.json

{
 "ConnectionStrings": {
 "DefaultConnection": "Server=XXXXXX,1433;Initial Catalog=XXXXXX;Persist Security Info=False;User ID=XXXXXXX;Password=XXXXXXX;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;",
 }
}

This is great, and if it is a part of a new web application, then migrations is auto setup for you.  But what if you have another database that you want to build a model for, set up its context, then inject into your controllers…

Injecting an existing DB and DB Context

If you would like to learn how to “reverse engineer” your database tables into a c# model, check out this post.

If you ran the linked above “scaffold” command to create your model and context, you will see that the  connection string is set in the OnConfiguring() method or you new context.


        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            #warning To protect potentially sensitive information in your connection string, you should move it out of source code. See http://go.microsoft.com/fwlink/?LinkId=723263 for guidance on storing connection strings.
            optionsBuilder.UseSqlServer(@"XXXXXt;Database=XXXXX;user id=XXXXX;password=XXXXX;");
        }

Delete the entire above OnConfiguring() method. Replace it with a constructor for your context (below) and pass it the DB  options that we will setup next, in our Startup.cs class

        public SunstackContext(DbContextOptions<MyNewContext> options) : base(options)
        {
            //any changes to the context options can now be done here
        }

Next, we want to add the database’s connection string to appsettings.json

  "ConnectionStrings": {
    "DefaultConnection": "Server=XXXXX,1433;Initial Catalog=XXXXX;Persist Security Info=False;User ID=XXXXXX;Password=XXXXXX;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;",
    "MyNewConnection": "XXXXXX,1433;Initial Catalog=XXXXX;Persist Security Info=False;User ID=XXXXX;Password=XXXXX;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"
  },

And then we hook up this DBContext to your services in ConfigureServices()

        public void ConfigureServices(IServiceCollection services)
        {

            // Add User DB connection
            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

            //Add My New DB connection
            services.AddDbContext<MyNewContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("MyNewConnection")
                ));

            ..........

        }

At this point everything should build!!
We now have the new context setup and ready to inject into a controller.  The last step is very easy, just add our new service to ANY controller’s constructor, here is  simple example.

    public class FileManagerController : Controller
    {
        MyNewContext _myNewContext;

        public FileManagerController(MyNewContext context)
        {
            _myNewContext = context;
        }

    }

 

Advertisements

5 thoughts on “ASP.NET Core: Injecting your DB Context into your Controllers

  1. Ethan Miller January 4, 2017 / 2:40 pm

    Very interesting arguments, I basically agree with you!

    Like

  2. CG August 5, 2017 / 11:35 pm

    UseSqlServer does not exist.

    Like

    • jesse April 18, 2018 / 1:21 pm

      I believe UseSQLServer comes from DBContextOptionsBuilder – To user this you must use/import the Microsoft.EntityFrameworkCore context

      using Microsoft.EntityFrameworkCore;

      Like

  3. kksingla027 February 19, 2018 / 12:34 pm

    Entities should not be referenced directly into Controller project. It should be referenced to Business project and your business should be referenced to Controller Project.

    But in .Net core, we are injecting our entity context as DI so am trying to figure out the way how to do it without adding entity reference to controller project.

    Like

  4. Cedric HENRY February 22, 2018 / 12:40 pm

    As DbContext implements the IDisposable interface, I would be interested to know how/when the ASP.NET framework handles the disposing of the DbContext instances.

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s