Last updated: October 26, 2023
Entity Framework Core (EF Core) is a modern object-relational mapper (ORM) for .NET that supports LINQ queries, change tracking, updates, and schema migrations. It offers flexibility in how you approach database development, allowing you to choose the strategy that best fits your project's needs and team's expertise.
This document explores the primary development approaches for EF Core, helping you understand their strengths, weaknesses, and when to apply them.
Code-First is the most common and often recommended approach for new projects. In this model, your domain classes (Plain Old CLR Objects - POCOs) are defined first. EF Core then infers the database schema based on these classes and their relationships.
Your entities are simple C# classes. EF Core uses conventions and data annotations to map these classes to database tables and their properties to columns.
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
public virtual ICollection<Post> Posts { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogId { get; set; }
public virtual Blog Blog { get; set; }
}
You define a class that derives from DbContext
and includes DbSet<TEntity>
properties for each entity in your model.
using Microsoft.EntityFrameworkCore;
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
// Example connection string
optionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=BloggingEFCore;Trusted_Connection=True;");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Fluent API configurations can be added here
modelBuilder.Entity<Blog>().HasKey(b => b.BlogId);
modelBuilder.Entity<Post>().Property(p => p.Title).IsRequired();
}
}
EF Core Migrations allow you to evolve your database schema over time as your model changes. You can generate migration scripts and apply them to your database.
Key commands (run in Package Manager Console or .NET CLI):
Add-Migration InitialCreate
(Package Manager Console) or dotnet ef migrations add InitialCreate
(.NET CLI)Update-Database
(Package Manager Console) or dotnet ef database update
(.NET CLI)In Database-First, you start with an existing database. EF Core scaffolding tools are used to reverse-engineer the database schema and generate entity classes and a DbContext
.
You typically use the EF Core scaffolding command-line tools.
Example using .NET CLI:
dotnet tool install --global dotnet-ef
dotnet ef dbcontext scaffold "Server=your_server;Database=your_database;Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer -o Models
This command connects to your database, reads the schema, and generates C# classes in the specified output directory (Models
in this example).
The scaffolding process generates:
DbContext
class configured to connect to your database.OnModelCreating
).Model-First involves designing your data model graphically, often using tools like the ADO.NET Entity Data Model Designer in Visual Studio. EF Core can then generate the database schema from this model or reverse-engineer it into code.
While possible, Model-First is less frequently used with EF Core compared to EF6. EF Core's strong emphasis on Code-First and Database-First (via scaffolding) generally covers most modern use cases more efficiently.
The best approach depends on your project's context:
It's also possible to adopt a hybrid approach. For instance, you might scaffold an existing database to get started (Database-First) but then gradually migrate towards a Code-First model over time as you refactor or add new features.