Entity Framework (EF)
Entity Framework (EF) is a set of Data Access technologies for .NET applications that enables developers to interact with relational data using domain-specific objects, eliminating the need for most of the data-access code that developers traditionally need to write.
Table of Contents
Introduction to Entity Framework
Entity Framework is Microsoft's object-relational mapper (ORM) for the .NET framework. It allows developers to work with databases using .NET objects, simplifying data access and reducing boilerplate code. EF translates queries written in LINQ (Language Integrated Query) into SQL statements that are executed against the database.
Key benefits of using Entity Framework include:
- Productivity: Reduces the amount of data access code you need to write.
- Maintainability: Makes your data access code cleaner and easier to manage.
- Abstraction: Abstracts away the underlying database, making it easier to switch database providers.
- Type Safety: Leverages the power of C# and LINQ for type-safe queries.
EF Core vs. EF6
Entity Framework has evolved significantly over the years. The two primary versions you'll encounter are:
- EF Core: The latest generation of Entity Framework. It's a complete rewrite, cross-platform, and offers improved performance and extensibility. It's the recommended choice for new .NET applications.
- EF6: The previous stable release. While still widely used, it's not under active development for new features.
For new projects, always consider using EF Core.
Getting Started
To start using Entity Framework Core, you typically need to install the necessary NuGet packages. For a basic setup, you'll need:
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Tools
Next, you'll define your data model (your entities) and a DbContext
class, which represents a session with the database and allows you to query and save data.
Example: Defining an Entity
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; }
}
Example: Defining a DbContext
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)
{
optionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=Blogging;Trusted_Connection=True;");
}
}
Code-First Approach
The Code-First approach allows you to define your domain model classes first, and then EF Core creates the database schema based on your classes. This is often the preferred approach for new development.
You define your entities and DbContext
as shown in the "Getting Started" section. Then, you use EF Core Migrations to generate and apply the database schema.
Database-First Approach
With the Database-First approach, you start with an existing database, and EF Core generates the model classes and DbContext
from it. This is useful when you're working with legacy databases or when a DBA provides you with a schema.
You can use the EF Core Power Tools (available as a Visual Studio extension) or the command-line interface to scaffold your model from an existing database.
Model-First Approach
The Model-First approach involves designing your conceptual model using a visual designer (like the one in Visual Studio), and then EF generates both the code and the database schema from that model. This approach is less common now, with EF Core favoring Code-First.
Querying Data
Entity Framework allows you to query your data using LINQ. The DbContext
exposes DbSet<TEntity>
properties, which represent collections of entities in the database.
Example: Fetching all blogs
using (var context = new BloggingContext())
{
var blogs = context.Blogs.ToList();
foreach (var blog in blogs)
{
Console.WriteLine($"Blog URL: {blog.Url}");
}
}
Example: Filtering and Including Related Data
using (var context = new BloggingContext())
{
var aspNetBlogs = context.Blogs
.Where(b => b.Url.Contains("asp.net"))
.OrderBy(b => b.Url)
.ToList();
var firstBlogWithPosts = context.Blogs
.Include(b => b.Posts) // Eagerly load Posts
.FirstOrDefault();
}
See the LINQ documentation for more details on query syntax.
Saving Changes
After modifying entities (adding, updating, or deleting), you call SaveChanges()
on the DbContext
to persist those changes to the database.
Example: Adding a new blog
using (var context = new BloggingContext())
{
var newBlog = new Blog { Url = "https://example.com/newblog" };
context.Blogs.Add(newBlog);
context.SaveChanges(); // Inserts the new blog
}
Example: Updating a blog
using (var context = new BloggingContext())
{
var blogToUpdate = context.Blogs.Find(1); // Assuming a blog with ID 1 exists
if (blogToUpdate != null)
{
blogToUpdate.Url = "https://example.com/updatedblog";
context.SaveChanges(); // Updates the blog's URL
}
}
Example: Deleting a blog
using (var context = new BloggingContext())
{
var blogToDelete = context.Blogs.Find(2); // Assuming a blog with ID 2 exists
if (blogToDelete != null)
{
context.Blogs.Remove(blogToDelete);
context.SaveChanges(); // Deletes the blog
}
}
Migrations
EF Core Migrations are a way to incrementally update your database schema to keep it in sync with your data model. They allow you to evolve your database schema over time without losing data.
Common commands:
dotnet ef migrations add InitialCreate
: Creates a new migration.dotnet ef database update
: Applies pending migrations to the database.dotnet ef migrations remove
: Removes the last migration.
Migrations are stored as C# classes and can be reviewed and modified.
Advanced Topics
Entity Framework offers many advanced features:
- Transactions: Managing database transactions for atomicity.
- Concurrency Control: Handling concurrent updates to the same data.
- Stored Procedures: Calling stored procedures from your .NET code.
- Raw SQL Queries: Executing raw SQL queries when LINQ is not sufficient.
- Change Tracking: Understanding how EF tracks entity state.
- Performance Tuning: Optimizing queries and EF configurations.
- Lazy Loading, Eager Loading, Explicit Loading: Different strategies for loading related data.
Explore the detailed advanced topics section for in-depth guidance.