.net is a free cross-platform, open source developer platform to help software developers develop different types of applications. Using .net provides developers the ability to use a variety of different languages, editors and libraries to develop applicationsfd for web, mobile, desktop, gaming and IoT.
Entity Framework Core is an Object Relational Mapper (ORM) for .net Core projects, supported by Microsoft, enabling developers to work with data using objects of domain specific classes without focusing on the underlying database tables and columns where the data is stored. Using Entity Framework developers work at a higher level of abstraction which helps to create and maintain data oriented applications with less code and without having to work directly within in the Database platform.
Entity Framework Features
- Cross-platform: EF Core is a cross-platform framework which can run on Windows, Linux and Mac
- Modelling: Entity Framework creates POCO (Plain Old CLR Object) entities using get/set properties of different data types.
- Change Tracking: tracks of changes occurred to instances of entities (Property values) which need to be submitted to the database.
- Concurrency: Optimistic Concurrency by default to protect overwriting changes made by another user since data was fetched from the database.
- Transactions: automatic transaction management while querying or saving data, with options to further customise transaction management.
- Caching: First level of caching out of the box. Repeated querys will return data from the cache instead of hitting the database
- Configurations: Configure EF model by using data annotation attributes or Fluent API to override default conventions.
- Migrations: Set of migration commands that can be executed on the NuGet Package Manager Console or the Command Line Interface to create or manage underlying database Schema.
In this post we will walk you through the process of running creating a simple EF Core Database, with Migrations with Entity Model and Database Contexts in separate class libraries in a .net core Web Api project.
The Web API itself will be responsible for maintaining a list of known Referrer Spammers.
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.
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
loadon 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 and a Service Layer pattern this will usually help to ensure that no database logic or interference bleeds into the business logic of your application.
Create 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. Eventually for this particular project, we are going to create Database context for three of the main database providers. i.e. Postgres, Mysql and MS SQL.
We will mainly be dealing with the PostgreSQL context in this article. The primary reason why we will be creating separate projects for each of the anticipated contexts, is that there are a number of quirks of each Relational Database system that will need to catered for in each of the different contexts.
Although it is true, that EF core in theory enables you to connect and interact with many different data sources, you still need to cater for the slight quirks of the different databases within the DbContexts. I will walk-through some of these within this article.
Rename the generated class to
We’ll also add a reference
In the case and purpose we going to use PostgreSQL
So let’s go ahead and add a reference to those packages too.
We can now create a barebones Database Context.
We’ll now create a new project which we’ll use to create a Database Entity objects we’ll call it rather unimaginatively
Api.Database.Entity. The primary reason why we will be creating this as a totally separate project is to enable the referencing of entities across our various projects and Context Projects.
For the sake of example, We’ll create 3 additional classes:
How to create a Database Context
DbContext is an important class in Entity Framework API. It is a bridge between your domain or entity classes and the database.
- The primary class that is responsible for interacting with data as objects DbContext.
- DbContext APIs simplify your application interaction with the database.
- Reduces the number of methods and properties required to access commonly used tasks.
The Entity Framework API’s are not released as part of the .net core framework and an additional step if required to install them locally on your machine, if you would like to use them for either Code-First or Database-First Development. To install the EF Core APi’s globally – you can use them across any project -simply execute the following command in your terminal window:
We are now ready to edit our previously created
SwcContext.cs and class library project to include a reference to our
How to define Entity Configuration
Earlier in this post, I pointed out that I prefer to keep my entities as simple POCO classes and I don’t use the Component Annotations to define the database properties. My preference for this is to make use of
IEntityTypeConfiguration, this is based on ensuring the Separation of Concerns principle and decoupling the persistence layer from the domain model logic. Principles defined in Eric Evans Domain-Driven Design: Tackling Complexity in the Heart of Software
IEntityTypeConfiguration enables configuration for an entity type to be factored into a separate class, rather than in-line in
OnModelCreating. Implement this interface, applying configuration for the entity in the
Configure method, and then apply the configuration to the model using
Once we have finished creating all our Entity Type Configuration classes we just need to update our SwcContext to use use them.
How to Define Migrations Assembly
The default behaviour of EF core is to place the Migration script with the assembly that defines the DbContext.
If you want to change the default behaviour, to say place the migrations script within your Web Application or API project, then you can make use of the
DbContextOptionsBuilder and the 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
For my particular project, I am not going to do this, because I would like to keep all my database specific code within my database project.
How to create a DbContextFactory
We now need to create factory class for creating derived DbContext instances. This class will Implement the
IDesignTimeDbContextFactory interface to enable design-time services for context types that do not have a public default constructor.
At design-time, derived DbContext instances can be created in order to enable specific design-time experiences such as model rendering, DDL generation etc.
Design-time services will auto-discover implementations of this interface that are in the same assembly as the derived DbContext type.
The ContextFactory is an implementation and example of the Factory Design pattern that is fairly common within the .net core framework code base.
In order to implement this factory we will need to add and additional class to our project and call it
How to create Entity Framework Core Migration
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:
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
To view the SQL script your Migrations will use for your specific Database environment.
Check out the full list of Migration Commands
Open a Terminal window and navigate to the folder containing Api.Database.Postgre.csproj i.e.
cd Api.Database.Postgre. Due to the fact that we have created a Api.Database.Postgre as Class library project we will not be able to execute our dotnet ef commands directly against it, we will have to use the API as the startup project. Notice
After this command has completed you will notice a new folder has been created in your Database project, which will contain the migration scripts, however these scripts have not been applied to your database yet.
We can execute these scripts against our database to create database. Using the following command
We can open our Database in whichever client we prefer. I use Jetbrains Rider which has a Database viewer and installed the PostgreSQL driver. I can then simply connect to my database and navigate to it to view
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.
- How to use Github actions to build & deploy Github nuget packages - October 14, 2021
- How to implement cross cutting concerns with MediatR Pipeline Behaviours - October 5, 2021
- Understanding the difference between Queue and Stack Data Structure - September 22, 2021