Using EF Core in a Separate Class Library project

Entity Framework Core is an Object Relational Mapper (ORM) for ASP.net Core projects, really easy to use and to get up and running really quickly.

An important reason to use an ORM is to enable an object-oriented business model and still be able to store and query a relational database.

When using Entity Framework Core there are a couple of ways to Run Migrations from a Separate class library.

In this post I will walk you through the process of running EF Core migrations from NET Standard Class Library.

Information

Update .net core 2.1
Entity Framework Core 2.1 added new seeding and migrations features.
Contrary to the previous versions of Entity Framework Core creating migrations from external assemblies is now even easier.

I have attempted to update this post with the new mechanism.

Often developers will aim to ensure their Database layer is entirely separate from business logic. In a lot of cases, they will also like to have their Database Entities and Domain entities as separate entities preferring to Map between these and only use Domain entities in the within their business logic.

These are best practices and software design patterns defined in Patterns of Enterprise Application Architecture and

Using an ORM, you should ensure to make your model objects as simple as possible. Be more vigilant about simplicity to make sure your model objects really are just Plain Old Data Objects (PODO), otherwise you may end up wrestling with your ORM to make sure the persistence works like you expect it to, and it’s not looking for methods and properties that aren’t actually there.

The Benefits of using ORM’s include:

  • Facilitates implementing domain model pattern.
  • A huge reduction in code.
  • Takes care of vendor-specific code by itself.
  • Cache Management – Entities are cached in memory thereby reducing the load on the DB.

To further abstract your Database logic from your business logic you may want to implement what is known as the Generic Repository Pattern

Add Database Class Library Project

We make use of solution and projects files in the source code, so if you are not familiar with working with solution files using .net core you may want to check out my post – Creating and Editing Solutions files with .net core CLI.

I’ll add a new class library project, primary purpose of this project is to create Database Context object which well share across a couple of projects.

Shell

Rename the generated class to ApiContext.cs

We’ll also add a reference to Microsoft.EntityFrameworkCore. In the terminal window you can use:

Shell

.In our case we are going to use Microsoft SQL Server 2017, as database server.

So let’s go ahead and add a reference to those packages too.

Shell

We can now create a barebones Database Context.

C#

Database Entities

We’ll now create a new project which we’ll use to create a Database Entity objects we’ll call it rather unimaginetively Api.Database.Entity.

The default class created via the project template we’ll rename to BaseEntity.cs and we’ll add some basic entity properties we need.

C#

We’ll also add an additional folder to the Entity Project and call it Threats.

For the sake of example, We’ll create 3 additional classes:

  • Status.cs
  • Threat.cs
  • ThreatType.cs

To View the properties of the file check the source code repository

Add Reference to Entity

We now need to add a reference for our Entity Project project to the Database Project.

Shell

For the purpose of my project I will create a static class which will be used to store all our constant string declarations, called DBGlobals .

We do this in order to try and minimize the use of Magic Strings or numbers in our code and we have one consistent string we can use throughout our library.

To learn more about minimising the use of Magic Strings and Numbers within your code, I recommend reading Java By Comparison: Become a Java Craftsman in 70 Examples. Although the book is mostly about Java, you’ll find that many of the suggestions pertain just as much to C#

We’ll declare a constant string SchemaName

C#

View Code
Review the Api.Database.csproj to ensure the 2 Nuget Packages have been added.

  • Microsoft.EntityFrameworkCore.Design
  • Microsoft.EntityFrameworkCore.Tools.DotNet

We are now ready to update, ApiContext.cs with additional logic

C#

Our EF Core work is now complete. We have a basic Schema, and we have developed our Context, for the most part we are done. All we need to do now is create the Migration to get our Database up and running.

I will illustrate how we will make use of SQL Server 2016, running within a Docker Container to enable testing of the Migration Scripts. I won’t discuss how to get started with SQL Server and Docker. Microsoft do a pretty good job of explaining Connect to SQL Server on Linux

Check out install Docker for Ubuntu Developers

Define Migrations Assembly

Once you have created your EF Database project and have referenced it from your application project. You can use the API extensions that I believe have been shipped with EF Core 2.1. I only stumbled across them then other day while setting up a new project.

Advice

If you don’t define a Migrations Assembly, EF will default to placing the migrations code to the library where the repository is defined.

If you want to have your separate library to contain the migrations, then there is no need to define a migrations library. However, if you want your API or web project to contain the migration code, then you need to configure the migrations library.

This is up to your or your organisations best practice guidelines.

In this post, I will just provide instructions on how to make use of the MigrationsAssembly feature.

The DbContextOptionsBuilder now seems to have a new MigrationsAssembly method which you can pass the name of the assembly which you would like to include the Migrations in. You define this by adding options when add the context configuriton during the ConfigureServices in your application Startup.cs

C#

Once this is done you can now, as in my case I tend to the terminal window in Rider : cross platform .net IDE , to navigate to my project directory and simply use:

Shell

For the curious, who want to take a look and examine the SQL Scripts that will be generated to create the migrations you can use

Shell

To view the SQL script your Migrations will use for your specific Database environment.

Check out the full list of Migration Commands

Create Entity Framework Core Migration

Open a Terminal window and navigate to the folder containing Api.Database.csproj i.e. cd Api.Database.

If you’re using Visual Studio Code you can use the Integrated Terminal Window, or in I like to use Whack Whack Terminal – a terminal emulator for Visual Studio 2017, so you can click on the project then use ctrl + & ctrl + to open a terminal window. For the purpose of this post we will focus on using Visual Studio Code.

Once you have a terminal window open, in the directory of your database project, you can execute

Shell

This will create the migration. Notice the --startup-project provided using the directory path to the API project.

When setting up an EF Core project ensure the CSproj file has the following references

HTML

Add reference the EF Library

In order to make use of our seperate library we will need to edit the StartUp.cs to add our Context to the Services Collection.

In my case, I make use of Microsoft SQL Server, so I will also need to add the following Nuget Packages to the API Project

Shell
C#

Summary

Using the above technique you can encapsulate all your database logic within a separate class library project that you can share across multiple projects. You will not be dependent on any project to build or execute any database changes, the result being all your database activities are encapsulated and constrained to one library.

To expand further on this example, you may want to read How to seed your EF Core Database, to find out how you can further isolate and manage your database concerns using EF Core.

Watch The Video

After receiving a few questions about this post, I thought I would create a quick video together to walk through the process and explain the code I use in this example. There may be some additional content with further explanations in the video that I have not totally covered in this blog post.

The video is totally unscripted and I am basically providing and explanation by walking through the implementation of the pattern above. If you need any further explanation, or are still unclear please do just leave a comment and I will attempt to explain further.

Gary Woodfine

Freelance Full Stack Developer at threenine.co.uk
Helps businesses by improving their technical proficiencies and eliminating waste from the software development pipelines.

A unique background as business owner, marketing, software development and business development ensures that he can offer the optimum business consultancy services across a wide spectrum of business challenges.