left-icon

Entity Framework Core Succinctly®
by Ricardo Peres

Previous
Chapter

of
A
A
A

CHAPTER 2

Database

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:

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.

The __MigrationHistory table after the named migration

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.

 Returning to the initial database version

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.

Reverting to a named version

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.

Listing all applied migrations

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(/* … */);

  }

}

Scroll To Top
Disclaimer

DISCLAIMER: Web reader is currently in beta. Please report any issues through our support system. PDF and Kindle format files are also available for download.

Previous

Next



You are one step away from downloading ebooks from the Succinctly® series premier collection!
A confirmation has been sent to your email address. Please check and confirm your email subscription to complete the download.