.NET Core — Using Entity Framework Core in a separate Project

Rodrigo Santos
oppr
Published in
5 min readApr 13, 2019

From the .NET documentation, “Entity Framework Core is a cross-platform version of Entity Framework data access technology”. It is used as an Object Relational Mapper (ORM), which makes the work of dealing with the database easier, since developers can interact with it using .NET objects (models), avoiding the usage of database specific code.

Link to the same article on my blog here.

Most of the times, developers try to ensure that the Data Access Layer is entirely separated from the Business Logic of an application. These and others are considered best practices regarding software development, providing modularity and the principle of separation of concerns to an application.

In this post, we will build an example application that separates a .NET Core solution into three separates projects: a business logic project, a data access layer project and a web API project.

Setting up the solution in Visual Studio

Open up Visual Studio and create a solution that contains three projects with the following names:

  • MyCookingMaster.BL (Class Library) → corresponds to the business logic where we will place our Models.
  • MyCookingMaster.DAL (Class Library) → corresponds to the data access layer. Here we are going to place everything regarding Entity Framework Core (DbContext and Migrations).
  • MyCookingMaster.API (ASP.NET Core Web Application — API) → our startup project.

Next, we’ll set the dependencies in each one of the projects. The DAL project has a dependency to the BL project in order to use the models that we will build. To do this, right click in the dependencies of the DAL project and select Add Reference… In the window that pops up, select the BL project and click Ok.

In the API project, follow the same steps and add references to the BL and DAL project.

Business Layer Project

In this project we will build our models. It will be just a simple Recipes application model. Users can create recipes and see other recipes that were created by other users. Of course, for simplification reasons, it is not an exaustive model because it is not the main focus of the post.

Adding a database connection

Access the appsettings.json file in the API project and provide a database connection.

Data Access Layer Project

Now that we have our Models in the BL Project and our database connection string in the API project, let’s go ahead and configure the DAL project.

We will need to have a reference to the following packages:

Microsoft.EntityFrameworkCore

Microsoft.EntityFrameworkCore.Design (This package is required for the Entity Framework Core Tools to work)

Microsoft.EntityFrameworkCore.SqlServer (We are going to use a SQL Server database)

It is time to define our DbContext.

Inside the DAL project, create a class named ApplicationDbContext containing the following code.

Now, try to run one of the following commands inside the DAL project.

.NET CLIdotnet ef migrations add Initial

NuGet Package Manager ConsoleAdd-Migration Initial

“Unable to create an object of type ‘ApplicationDbContext’. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728"

Error? Erm… Hmm… What happened?

When we try to run the migrations, Entity Framework Tools tries to obtain the DbContext object from the application’s service provider. The problem is that the DAL project is a Class Library Project and NOT an ASP.NET Core Application/API. Next, it tries to create an instance using a constructor with no parameters from the derived DbContext (ApplicationDbContext in our case), which also does not apply.

There is other way we can tell Entity Framework Tools how to create our DbContext by implementing the IDesignTimeDbContextFactory<TContext> interface. From the .NET Core documentation:

“If a class implementing this interface is found in either the same project as the derived DbContext or in the application’s startup project, the tools bypass the other ways of creating the DbContext and use the design-time factory instead.”

Keeping all this in mind, let’s add the following code to ApplicationDbContext.cs file:

In order to resolve SetBasePath add the Microsoft.Extensions.Configuration.FileExtensions package. To resolve AddJsonFile, add a reference to the Microsoft.Extensions.Configuration.Json package.

We are now ready to run an initial migration.

.NET CLIdotnet ef migrations add Initial

NuGet Package Manager ConsoleAdd-Migration Initial

And there you have it! An initial migration was created in the DAL project in the Migrations folder. Everytime we need to make a new migration, we just need to run the command inside the DAL project.

We can now create the database.

.NET CLIdotnet ef database update

NuGet Package Manager ConsoleUpdate-Database

Seeding the database (Optional)

In order to test all our implementation, let’s also seed the database with some dummy data to be returned by the API. Create a file named DataSeeder.cs and add the following code.

We need also to add some code in our API project, namely in Program.cs .

API Project

In order to our API project use the context we defined in the DAL project, it must be added through Dependency Injection in Startup.cs file. We also add some JSON Options just to avoid reference loops when returning JSON to the client.

Finally, we create a controller that can handle CRUD operations on the Clients.

Run the API and access the ‘api/clients’ endpoint. If the database was seeded previously, it will show the data in JSON format.

Conclusion

And there you have it, our business logic and data access layer/entity framework are completely separated from our API. With this approach, all database logic is encapsulated into one project and can be shared across many projects in case we need.

Link to the same article on my blog here.

Source code: GitHub

Supporters

Our organization is a non-profit organization. However, we have many expenses across our activity. From infrastructure to service expenses, we need some money, as well as help, to support our team and projects. For the expenses, we created several channels that will mitigate this problem. First of all, you can support us by being one of our Patreons. Second, you can support us on Open Collective page. Thirdly, you can buy one coffee (or more) for us. Fourth, you can also support us on our Liberapay page. Last but not least, you can directly support us on PayPal. On the other hand, we also need help in the development of our projects. Therefore, if you have the knowledge we welcome you to support our projects. Just follow our channels and repositories.

--

--

Rodrigo Santos
oppr
Writer for

Full-Stack developer with a great passion to learn. NET Core enthusiast. More about me in https://www.rodrigo-santos.me