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:
- Have a defined database: We start with a defined database
- Scaffold: Use the command to generate the entities and the DbContext
- 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>”
- “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.
}
}
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; }
}
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.
