Entity Framework Code First: Setup and Usage
Entity Framework Code First is an approach to building database-driven applications where you define your data model using C# classes first, and Entity Framework automatically creates the database schema based on those models. This approach provides flexibility, version control friendliness, and a code-centric development experience.
Prerequisites
Before you start, ensure you have:
- Visual Studio or Visual Studio Code
- A .NET project (Framework or .NET Core/8)
- NuGet Package Manager installed
Step 1: Install Entity Framework
Install Entity Framework via NuGet Package Manager. Open the Package Manager Console and run:
Install-Package EntityFramework
For .NET Core/.NET 5+, use:
Install-Package Microsoft.EntityFrameworkCore
Step 2: Define Your Model Classes
Create C# classes that represent your database entities. Each class will become a table in the database.
using System;
using System.Collections.Generic;
public class Customer
{
public int CustomerId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public DateTime CreatedDate { get; set; }
// Navigation property for related orders
public virtual ICollection Orders { get; set; }
}
public class Order
{
public int OrderId { get; set; }
public int CustomerId { get; set; }
public decimal Total { get; set; }
public DateTime OrderDate { get; set; }
// Foreign key and navigation property
public virtual Customer Customer { get; set; }
}
Step 3: Create a DbContext
The DbContext is the main class that coordinates Entity Framework functionality. It represents
a session with the database and allows you to query and save data.
using Microsoft.EntityFrameworkCore;
public class MyApplicationContext : DbContext
{
public DbSet Customers { get; set; }
public DbSet Orders { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Server=YOUR_SERVER;Database=MyAppDb;Trusted_Connection=true;");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// Configure relationships, indexes, and constraints here
modelBuilder.Entity()
.HasOne(o => o.Customer)
.WithMany(c => c.Orders)
.HasForeignKey(o => o.CustomerId);
}
}
Step 4: Create and Apply Migrations
Migrations allow you to version control your database schema. Enable migrations and create the initial migration:
Enable-Migrations
Add-Migration InitialCreate
This creates a migration file in your Migrations folder. To apply the migration to your database:
Update-Database
Your database and tables are now created!
Step 5: Query and Manipulate Data
Now you can use your context to query and save data:
using (var context = new MyApplicationContext())
{
// Create a new customer
var customer = new Customer
{
FirstName = "John",
LastName = "Doe",
Email = "john.doe@example.com",
CreatedDate = DateTime.Now
};
context.Customers.Add(customer);
context.SaveChanges();
// Query customers
var customers = context.Customers.Where(c => c.LastName == "Doe").ToList();
// Update a customer
var existingCustomer = context.Customers.FirstOrDefault(c => c.CustomerId == 1);
if (existingCustomer != null)
{
existingCustomer.Email = "newemail@example.com";
context.SaveChanges();
}
// Delete a customer
context.Customers.Remove(existingCustomer);
context.SaveChanges();
}
Step 6: Working with Relationships
Entity Framework handles relationships between entities:
// Load customer with related orders (Eager Loading)
var customerWithOrders = context.Customers
.Include(c => c.Orders)
.FirstOrDefault(c => c.CustomerId == 1);
// Create an order for a customer
var newOrder = new Order
{
CustomerId = 1,
Total = 150.00m,
OrderDate = DateTime.Now
};
context.Orders.Add(newOrder);
context.SaveChanges();
Common Configurations
Customize your model behavior using Fluent API in OnModelCreating:
modelBuilder.Entity(entity =>
{
entity.HasKey(c => c.CustomerId);
entity.Property(c => c.Email).IsRequired().HasMaxLength(255);
entity.Property(c => c.FirstName).IsRequired().HasMaxLength(100);
entity.HasIndex(c => c.Email).IsUnique();
});
modelBuilder.Entity(entity =>
{
entity.Property(o => o.Total).HasPrecision(10, 2);
});
Best Practices
- Use async/await: Use
ToListAsync(),SaveChangesAsync()for better performance - Leverage migrations: Always track schema changes with migrations
- Use dependency injection: Inject your DbContext rather than hardcoding connection strings
- Handle relationships carefully: Use
Include()for eager loading to avoid N+1 queries - Dispose DbContext: Always dispose your context using
usingstatements or dependency injection - Enable lazy loading judiciously: Be aware of performance implications
Troubleshooting
Issue: "No DbContext was found in assembly"
Solution: Ensure your DbContext is in the startup project and accessible to the migrations project.
Issue: "The connection string is not valid"
Solution: Verify your connection string in OnConfiguring or appsettings.json.

















