Entity Framework (EF) Code-First is a development approach that allows developers to create a data model by writing C# or VB.NET classes. EF then generates the database schema based on these classes. This empowers developers to focus on their domain model and business logic without being constrained by an existing database schema.
Introduction to Code-First
The Code-First paradigm in Entity Framework flips the traditional database-first approach. Instead of designing your database and then generating entity classes, you start by defining your entity classes. These classes represent your domain objects and their relationships. EF Code-First then inspects these classes and infers the structure of your database.
Key Benefits of Code-First
- Developer Productivity: Start coding your application's domain logic immediately without database setup.
- Domain-Centric Development: Design your data model around your business needs, not database constraints.
- Simplified Refactoring: Easily modify your entity classes and let EF update your database schema.
- Testability: Easier to create in-memory or mock databases for unit testing.
Getting Started with Code-First
To use Code-First, you'll typically need the EntityFramework NuGet package. Once installed, you define your entity classes and a DbContext
class that represents your session with the database and allows you to query and save data.
Defining Entity Classes
Entity classes are simple POCOs (Plain Old CLR Objects) that represent your data entities.
public class Product { public int ProductId { get; set; } public string Name { get; set; } public decimal Price { get; set; } public virtual ICollection<Order> Orders { get; set; } } public class Order { public int OrderId { get; set; } public DateTime OrderDate { get; set; } public decimal TotalAmount { get; set; } public int CustomerId { get; set; } public virtual Customer Customer { get; set; } } public class Customer { public int CustomerId { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public string Email { get; set; } public virtual ICollection<Order> Orders { get; set; } }
Defining the DbContext
The DbContext
class is the entry point to your database. It represents a session with the database and allows you to perform CRUD (Create, Read, Update, Delete) operations.
using System.Data.Entity; using System.Collections.Generic; public class MyDbContext : DbContext { public MyDbContext() : base("name=MyConnectionString") { // Optional: Configure database initialization strategy Database.SetInitializer(new CreateDatabaseIfNotExists<MyDbContext>()); } public DbSet<Product> Products { get; set; } public DbSet<Order> Orders { get; set; } public DbSet<Customer> Customers { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { // Optional: Configure model using Fluent API modelBuilder.Entity<Product>() .Property(p => p.Price) .HasPrecision(18, 2); modelBuilder.Entity<Order>() .HasRequired(o => o.Customer) .WithMany(c => c.Orders) .HasForeignKey(o => o.CustomerId); base.OnModelCreating(modelBuilder); } }
Database Migrations
When you make changes to your entity classes after the database has been created, you'll need to update the database schema. Entity Framework Migrations is the tool for this. It allows you to evolve your database schema over time in a controlled and scriptable manner.
Enabling Migrations
Open the Package Manager Console in Visual Studio and run:
Enable-Migrations
Creating a Migration
After enabling migrations and making changes to your model, you can create a migration:
Add-Migration InitialCreate
Applying Migrations
To apply the pending migrations to your database:
Update-Database
Advanced Concepts
Code-First offers extensive flexibility for customizing your data model and database interactions:
- Fluent API: Provides a programmatic way to configure your model and mapping, overriding conventions and attribute-based configurations.
- Data Annotations: Attributes like
[Key]
,[Required]
,[MaxLength]
, and[Column]
can be applied directly to your entity classes for basic configuration. - Relationships: EF Code-First automatically infers one-to-one, one-to-many, and many-to-many relationships based on your entity class definitions and navigation properties.
- Customizing Database Creation: Strategies like `CreateDatabaseIfNotExists`, `DropCreateDatabaseAlways`, and `MyCustomInitializer` allow control over how the database is initialized.