CHAPTER 2
Database
Configuring the connection string
We need to explicitly pass Entity Framework the connection string to use, which is related to a specific provider. We can do it in the OnConfiguring method, as follows:
Code Listing 47
public class ProjectsContext : DbContext { private readonly String _nameOrConnectionString; public ProjectsContext(String nameOrConnectionString) { _nameOrConnectionString = nameOrConnectionString; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlServer(_nameOrConnectionString); base.OnConfiguring(optionsBuilder); } } |
Another option is to use the base constructor that takes a DbContextOptions object:
Code Listing 48
public class ProjectsContext : DbContext { public ProjectsContext(DbContextOptions options) : base(options) { } private static DbContextOptions GetOptions(string connectionString) { var optionsBuilder = new DbContextOptionsBuilder(); return optionsBuilder.UseSqlServer(connectionString).Options; } } |
Generating the database
Explicit creation
The Code First model, as its name implies, comes before the database. Nevertheless, we still need it and have to create it. Entity Framework offers an API to do just that. If we decide that it should be created, we need to start a new context and ask it to do that for us by calling EnsureCreated:
Code Listing 49
using (var ctx = new ProjectsContext()) { //will create the database if it doesn’t already exist. ctx.Database.EnsureCreated(); } |
Tip: The user specified by the connection string, which can even be the current Windows user, must have access rights to create a database.
Tip: If the database already exists, Create will fail, and CreateIfNotExists will return false.
Database initializers
Entity Framework Core dropped database initializers—they are no longer included in the code.
Migrations
We all know that schema and data change over time, be it the addition of another column or a modification in a base record. Entity Framework Core offers a code-based approach for dealing with changes in schema: migrations.
Migrations offer fine-grained control over the generated model. We start by creating a migration with a name that describes our purpose, for which we will need some NuGet packages:
- https://www.nuget.org/packages/Microsoft.EntityFrameworkCore.Tools.DotNet as a DotNetCliToolReference in the .csproj file
- Microsoft.EntityFrameworkCore.Tools
For additional information, please refer to https://docs.microsoft.com/en-us/ef/core/get-started/aspnetcore/new-db.
And we execute Add-Migration in the Package Manager Console:
Add-Migration InitialVersion
Or, using the command line, do:
dotnet ef migrations add InitialCreate
This will only create the migrations classes, on the Migrations folder whose name reflects the name passed to Add-Migration and the timestamp of its creation, which inherits from class Migration. This new class is empty except for two method declarations, which are overridden from the base class:
- Up: will specify the changes that will be applied to the database when this migration is run.
- Down: will contain the reverse of the changes declared in the Up method, for the case when this migration is rolled back.
Note: This class is not specific to any Entity Framework Core context; it only cares about the database.
When Entity Framework creates a migration, it creates a __MigrationHistory table in the target database for data stores that support it, like relational databases, of course. This is where all migrations are tracked.
Let’s see a simple example.
Code Listing 50
public partial class InitialCreate : Migration { public override void Up() { /* … */ } public override void Down() { /* … */ } } |
As you can see, I didn’t show all contents of the Up method, all operations are reversed in the Down method.
The Migration class contains helper methods for most typical database operations, but in case we need something different, we can always use the Sql method:
Code Listing 51
Sql("-- some SQL command"); |
Now that we have this migration, we might as well execute it, using the command line:
dotnet ef database update
Or the Package Manager Console:
Update-Database -TargetMigration InitialCreate
Tip: Unlike previous versions, there is no longer a Seed method.
Once again, we can see that the __MigrationHistory table was updated.

Figure 13: The __MigrationHistory table after the named migration
We add new migrations by calling Add-Migration with some name. Of course, we can always go back to the previous state, or the state identified by any named migration that has been run, by using Update-Database.

Figure 14: Returning to the initial database version
If you want to revert to a named migration, just pass its name as a parameter to Update-Database.
![]()
Figure 15: Reverting to a named version
At any time, you can see what migrations have been executed in the database by invoking the Get-Migrations command.
![]()
Figure 16: Listing all applied migrations
One final word of caution: to use migrations, your context needs to have a public, parameter-less constructor. Why? Because it needs to be instantiated through reflection by the migrations infrastructure, which has no way of knowing which parameters it should take. Strictly speaking, this is not entirely true: if the migrations framework can find a public implementation of IDesignTimeDbContextFactory<T> (used to be IDbContextFactory<T>, but this interface was deprecated in EF Core 2), where T is the type of your DbContext, then it will call its Create method automatically:
Code Listing 52
public class ProjectsContextFactory : IDesignTimeDbContextFactory<ProjectsContext> { public ProjectsContext Create(string [] args) { //create and return a new ProjectsContext. return new ProjectsContext(/* … */); } } |
- 1800+ high-performance UI components.
- Includes popular controls such as Grid, Chart, Scheduler, and more.
- 24x5 unlimited support by developers.