Entity Framework Core Data Access
This section delves into the core concepts and techniques for accessing data using Entity Framework Core (EF Core). EF Core is a modern, cross-platform Object-Relational Mapper (ORM) for .NET that enables developers to work with databases using .NET objects, eliminating the need for most of the data-access code they typically have to write.
The DbContext
The heart of EF Core is the DbContext class. It represents a session with the database and can be used to query and save data. You typically create a class that derives from DbContext and represents your entity data and the ability to query and save data from a particular database.
Defining Your DbContext
Here's a simple example of 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=BloggingEFCore;Trusted_Connection=True;");
}
}
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; }
}
DbSet<TEntity> properties on your context class represent collections of entities in the database. EF Core uses these to infer the schema.
Working with DbSets
DbSet<TEntity> properties allow you to query and manipulate collections of a specific entity type. You can access instances of these properties from your DbContext.
Querying Data
To query data, you access the DbSet<TEntity> property and then use LINQ to specify your query criteria.
using (var context = new BloggingContext())
{
var blogs = context.Blogs.Where(b => b.Url.Contains("example.com")).ToList();
foreach (var blog in blogs)
{
Console.WriteLine(blog.Url);
}
}
Saving Data
EF Core tracks changes made to entities that are retrieved from the context. When you call SaveChanges() or SaveChangesAsync(), EF Core determines what needs to be inserted, updated, or deleted in the database.
Adding New Entities
using (var context = new BloggingContext())
{
var newBlog = new Blog { Url = "http://new-blog.example.com" };
context.Blogs.Add(newBlog);
context.SaveChanges();
}
Updating Entities
When you retrieve an entity, modify its properties, and then call SaveChanges(), EF Core automatically detects and applies these changes.
using (var context = new BloggingContext())
{
var existingBlog = context.Blogs.Find(1); // Assuming blog with ID 1 exists
if (existingBlog != null)
{
existingBlog.Url = "http://updated-blog.example.com";
context.SaveChanges();
}
}
Deleting Entities
using (var context = new BloggingContext())
{
var blogToDelete = context.Blogs.Find(2); // Assuming blog with ID 2 exists
if (blogToDelete != null)
{
context.Blogs.Remove(blogToDelete);
context.SaveChanges();
}
}
SaveChanges() once is generally more efficient than calling it after each individual operation.
Entity States
EF Core tracks the state of each entity within the context. The common states are:
- Added: The entity will be inserted into the database.
- Unchanged: The entity has not been modified since it was retrieved or attached.
- Modified: The entity's properties have been changed.
- Deleted: The entity will be deleted from the database.
- Detached: The entity is not being tracked by the context.
Attaching and Detaching Entities
You can manually attach entities to a context if they were not loaded by it. This is useful when working with disconnected scenarios.
// Assuming 'detachedBlog' was created outside the current context
using (var context = new BloggingContext())
{
// Mark the entity as modified so EF Core knows to update it
context.Attach(detachedBlog);
context.Entry(detachedBlog).State = EntityState.Modified;
context.SaveChanges();
}