Entity Framework CRUD Operations
Entity Framework Core (EF Core) simplifies data access in .NET applications by providing an Object-Relational Mapper (ORM). CRUD operations are fundamental to any data-driven application, and EF Core makes these tasks straightforward and efficient.
Understanding the DbContext
The core of EF Core interaction is the DbContext class. It represents a session with the database and allows you to query and save data. You'll typically create a derived context class that exposes DbSet<TEntity> properties for each entity in your model.
// Example 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=BloggingEF;Trusted_Connection=True;");
}
}
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
public 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 Blog Blog { get; set; }
}
Create (Adding New Data)
To add new entities to the database, you first instantiate your DbContext, create an instance of your entity, add it to the appropriate DbSet, and then call SaveChanges().
using (var context = new BloggingContext())
{
var newBlog = new Blog { Url = "http://example.com/blog" };
context.Blogs.Add(newBlog);
context.SaveChanges(); // Inserts the new blog into the database
}
Read (Querying Data)
Reading data is typically done using LINQ to Entities. You can query directly from your DbSet properties.
Retrieving a Single Entity
Use methods like Find() (which first checks the local cache) or FirstOrDefaultAsync().
using (var context = new BloggingContext())
{
// Find by primary key
var blog = context.Blogs.Find(1);
// Find first matching a condition
var firstBlog = context.Blogs.FirstOrDefault(b => b.Url.Contains("example"));
}
Retrieving Multiple Entities
Iterate over the DbSet or use LINQ to filter and project.
using (var context = new BloggingContext())
{
var allBlogs = context.Blogs.ToList(); // Retrieves all blogs
var blogsWithPosts = context.Blogs
.Where(b => b.Posts.Any())
.ToList();
}
Update (Modifying Existing Data)
To update an entity, you first retrieve it from the database, modify its properties, and then call SaveChanges(). EF Core tracks changes automatically.
using (var context = new BloggingContext())
{
var blogToUpdate = context.Blogs.Find(1);
if (blogToUpdate != null)
{
blogToUpdate.Url = "http://updated-example.com/blog";
context.SaveChanges(); // Updates the blog in the database
}
}
DbContext instance, EF Core handles it automatically.
Delete (Removing Data)
Similar to updating, you retrieve the entity you want to delete, then call Remove() on the DbContext, followed by SaveChanges().
using (var context = new BloggingContext())
{
var blogToDelete = context.Blogs.Find(2);
if (blogToDelete != null)
{
context.Blogs.Remove(blogToDelete);
context.SaveChanges(); // Deletes the blog from the database
}
}
Best Practices
- Use `using` statements: Ensure your
DbContextis properly disposed of by wrapping its creation in ausingblock. - Minimize database round trips: Batch multiple
Add,Update, orRemoveoperations before callingSaveChanges(). - Asynchronous operations: For performance, especially in web applications, use asynchronous methods like
AddAsync(),SaveChangesAsync(), etc. - Error Handling: Implement robust error handling, especially around
SaveChanges(), as database operations can fail.
Asynchronous CRUD Operations
Leveraging asynchronous programming with EF Core can significantly improve the responsiveness and scalability of your application, particularly in I/O-bound scenarios like database access.
using (var context = new BloggingContext())
{
var newPost = new Post { Title = "Async Post", Content = "This is an async example.", BlogId = 1 };
await context.Posts.AddAsync(newPost);
await context.SaveChangesAsync(); // Asynchronously saves changes
}
using (var context = new BloggingContext())
{
var blog = await context.Blogs.FirstOrDefaultAsync(b => b.BlogId == 1);
if (blog != null)
{
// ... modify blog ...
await context.SaveChangesAsync();
}
}
Bulk Operations with EF Core Extensions
For very large numbers of entities, consider using third-party libraries like EF Core.BulkExtensions for significantly faster bulk insert, update, and delete operations.
Example using EF Core.BulkExtensions (requires installation via NuGet):
// using EFCore.BulkExtensions;
// List<Blog> blogsToAdd = ...;
// await context.BulkInsertAsync(blogsToAdd);
// List<Post> postsToUpdate = ...;
// await context.BulkUpdateAsync(postsToUpdate);
// List<int> blogIdsToDelete = ...;
// await context.Blogs.Where(b => blogIdsToDelete.Contains(b.BlogId)).BulkDeleteAsync();