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