How to Use Dependency Injection with EF Core In-Memory Database and Invoking Dependencies
In the last article in this series, I will show you two straightforward things: first, how to use the EntityFramework Core in memory and how to invoke an injected dependency without using the class constructor!
But why wouldn't you inject the dependency on the constructor, as I showed in the previous articles? Well, sometimes, it is necessary to use alternative mechanisms to simplify the development and have access to the objects!
For many years I wrote about EF, but as there was a long delay in the development of EF Core, I ended up using other ORMs in my projects. But now EF Core is fascinating, and I went back to using it on a massive project!
So, I decided to complement this series by showing an extremely useful feature of EF Core, which is the in-memory database.
But why so useful? Imagine that you develop using a "development" database or even local on your machine, which is perfectly normal. Still, over time this database can get "dirty," or with "bad" data, so we have to clean and start all over again.
Then think that you can keep an entire database in memory, performing the same operations that you would do in the typical database, but without saving anything anywhere except in the memory.
This feature is very valuable for unit tests, and I really hope you are writing tests!
For this example we are going to create an ASP.NET Core WebAPI project.
Creating the EF Core Context
The first thing we will do is create a class (table) and the context.
We will have a simple
Client class :
Now let's get to the
Our context has nothing much, except a
SeedData() method that I am using to fill the
Client table in memory.
Remember that I am using a memory database, so to have data, I need to fill this database when I start the context!
Now let's configure the services in the Startup class:
See that we are adding a context with the option
To use this method, you will need the following Entity packages:
InMemory package allows you to have a database in memory. See that you can exchange
UseSqlServer() or any other database provider, and everything is still working!
When I write unit tests, I create an
InMemory() context, and in the real application, I use a database! That makes my job much easier!
So we are injecting an Entity Framework context into our project through
AddDbContext(), and also two other classes:
IEnvioEmail), using Singleton and Scoped, which I showed in the previous article.
IHttpContextAccessor allows us to access the ASP.NET Core Http Context anywhere it is injected, and
IEnvioEmail is an example class that I created to simulate the sending of email.
See here the interface
IEnvioEmail and the class
This class "simulates" sending an email, I imagine you will implement a real class for this!
Working with Injection in the Controller
Now that we have our environment set up, let's create a controller to work with this data. We will create
ClientController.cs, which will have two actions:
Get() to bring all customers and
Email() to "simulate" the sending of email.
Let's go to the code:
Okay, we have a lot of things going on here, and I will explain:
In the controller constructor we are receiving some objects by injection:
ILogger logger= ASP.NET Core log
AplicacaoContext db= Entity Framework context
IHttpContextAccessor httpContextAccessor= Http Context of the application
All are assigned to variables within the controller. So let's go to the methods that interest us.
Get() method returns all database customers, which in our case are only in memory!
The other method,
Email(), is the one that we are going to show the "invocation" of a dependency without the constructor.
Understanding the scenario
That is more common than you think! In our project, we need to send an email, and the email class is in dependency injection (we set it up in
Startup.cs), but we don't put it in the controller constructor because it's a little-used method, and in this case, it doesn't justify it hypothetically! Or it is simply injected into another class, which is even more common! In any case, we do not have this class directly available.
So, let's "materialize" the object, looking for it in the dependency injector, see how simple it is:
var email = _httpContextAccessor.HttpContext.RequestServices.GetService<IEnvioEmail> ();
_httpContextAccessor is the application's Http context, which has
Request, which is the request for the page.
RequestServices.GetServices<IEnvioEmail>() which basically "asks" for the dependency injector to "give" us the object corresponding to the
That is very cool because you are "injecting" an object by hand. You are taking an object that is already created and bringing it to the variable
And now, let use the email!
Running the application, we will have the following result:
Now calling the email:
The dependency injection mechanism allows us to simplify development greatly! But use with care, as everything in excess is harmful!
Special thanks to my friend Rafael Almeida, with whom I "argue" frequently about EntityFramework!!! These discussions have already generated improvements in EF Core, such as
As always, the example code is on my Github.
Hugs, and see you soon!