entity-framework-database-first

Database First in Entity Framework

  • 4 min

One of the classic approaches when working with databases and Entity Framework is called Database First.

In this model, we start from an already existing database, and automatically generate the corresponding C# classes that allow us to interact with it through code.

The Database First approach is suitable when there is already a database with its tables, relationships, primary and foreign keys, and we want to work with it using EF Core.

This contrasts with the Code First approach: where we write the classes in C# and EF generates the database.

Workflow with Database-First

The workflow with Database-First consists of the following steps:

  1. Have a defined database: We start with a defined database
  2. Scaffold: Use the command to generate the entities and the DbContext
  3. Operations: Perform operations on the database

Basic syntax of the scaffold command

The Database First approach is mainly performed via the scaffold command, which is responsible for reading the database and generating the necessary code.

dotnet ef dbcontext scaffold “<connection_string>”[options]

  • “connection_string”: specifies how to connect to your database (don’t forget the "quotes")
  • provider: provider we will use
  • options: additional options

Complete command example

Let’s see it better with a typical example of what a complete scaffold command could look like.

dotnet ef dbcontext scaffold
“Server=localhost;Database=MiBD;Trusted_Connection=True;” Microsoft.EntityFrameworkCore.SqlServer
—output-dir Models
—context-dir Data
—context ComercioContext
—tables Clientes Pedidos
—no-onconfiguring
—use-database-names
—data-annotations
—force

  • Generate classes only for two tables. Clientes and Pedidos
  • With original names, in separate folders,
  • Without exposing the connection string in the code

Of course it’s just an example, and you will have to configure it to your project’s needs. But, more or less, you get the idea.

Structure of the generated code

When we run the command, and it finishes, the result is that two things will have been generated for us.

A DbContext class that represents the connection to the database and contains a DbSet for each table:

public partial class MiBaseDeDatosContext : DbContext
{
    public virtual DbSet<Cliente> Clientes { get; set; }
    public virtual DbSet<Pedido> Pedidos { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer("cadena_de_conexion");
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        // Here EF configures relationships, keys, etc.
    }
}
Copied!

A class for each table, with its properties mapped to the columns:

public partial class Cliente
{
    public int Id { get; set; }
    public string Nombre { get; set; }
    public string Email { get; set; }
}
Copied!

These classes are marked as partial, which allows us to extend them without touching the generated code, which is a good practice.

Do not modify the generated classes directly. Use partial class to extend them without losing changes when regenerating.

Re-generating the model after database changes

If at any point you change the database and want to regenerate the classes and delete the previous ones first* and run the previous command.

Alternatively, you can force overwriting using the --force option.

dotnet ef dbcontext scaffold “cadena” Microsoft.EntityFrameworkCore.SqlServer -o Models —force

The --force flag overwrites existing files.

Copied!