C# tutorials > Frameworks and Libraries > Entity Framework Core (EF Core) > Tracking and saving changes (SaveChanges, Add, Update, Remove)
Tracking and saving changes (SaveChanges, Add, Update, Remove)
Entity Framework Core (EF Core) is an ORM (Object-Relational Mapper) that simplifies database interactions in .NET applications. A core aspect of EF Core is tracking changes made to entities and persisting those changes to the database. This tutorial explores the SaveChanges, Add, Update, and Remove methods, which are fundamental to managing data persistence with EF Core.
Understanding Entity Tracking
EF Core automatically tracks changes made to entities retrieved from the database or added to the The DbContext. This tracking mechanism allows EF Core to determine which entities need to be inserted, updated, or deleted when SaveChanges is called.DbContext maintains a snapshot of each entity's original state. When SaveChanges is invoked, EF Core compares the current state of the entity with its original state. Any differences are translated into appropriate SQL commands (INSERT, UPDATE, DELETE) that are executed against the database.
Adding New Entities (Add)
The Add method marks an entity as new and signals to EF Core that it should be inserted into the database. This is demonstrated in the code snippet above, where a new Blog object is created and added to the Blogs DbSet. When SaveChanges is called, EF Core will generate and execute an INSERT statement for this new blog.
using Microsoft.EntityFrameworkCore;
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder options)
=> options.UseSqlite("Data Source=blogging.db");
}
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
public List<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; }
}
using (var context = new BloggingContext())
{
context.Blogs.Add(new Blog { Url = "http://example.com" });
context.SaveChanges();
}
Updating Existing Entities (Update)
The Important: In many cases, EF Core automatically detects changes without explicitly calling Update method explicitly marks an entity as modified. While EF Core often automatically detects changes, Update is useful when dealing with disconnected entities (entities that were not originally retrieved from the DbContext). In the code snippet, a Blog is retrieved, its Url property is modified, and then Update is called to ensure EF Core recognizes the change. After calling SaveChanges, EF Core will generate an UPDATE statement reflecting the modified URL.Update if the entity is being tracked. However, if you're working with disconnected entities or want to force an update, Update is necessary.
using (var context = new BloggingContext())
{
var blog = context.Blogs.Find(1); // Assuming a blog with ID 1 exists
if (blog != null)
{
blog.Url = "http://new-example.com";
context.Blogs.Update(blog); //explicitly mark to update
//context.ChangeTracker.DetectChanges();
context.SaveChanges();
}
}
Deleting Entities (Remove)
The Remove method marks an entity for deletion. In the code snippet, a Blog is retrieved and then marked for deletion using Remove. When SaveChanges is called, EF Core will generate and execute a DELETE statement for the specified blog.
using (var context = new BloggingContext())
{
var blog = context.Blogs.Find(1); // Assuming a blog with ID 1 exists
if (blog != null)
{
context.Blogs.Remove(blog);
context.SaveChanges();
}
}
Saving Changes (SaveChanges)
The SaveChanges method is the central point for persisting changes to the database. It examines all tracked entities and generates the appropriate SQL commands (INSERT, UPDATE, DELETE) based on the changes detected. It then executes these commands within a transaction. If any command fails, the entire transaction is rolled back, ensuring data consistency.
using (var context = new BloggingContext())
{
context.Blogs.Add(new Blog { Url = "http://example.com" });
context.SaveChanges(); // Persists changes to the database
}
SaveChangesAsync (Asynchronous Saving)
The SaveChangesAsync method is the asynchronous version of SaveChanges. It is highly recommended to use SaveChangesAsync in ASP.NET Core applications and other asynchronous environments to avoid blocking the main thread, improving the application's responsiveness.
using (var context = new BloggingContext())
{
context.Blogs.Add(new Blog { Url = "http://example.com" });
await context.SaveChangesAsync(); // Persists changes to the database asynchronously
}
Concepts behind the snippet
These methods directly interact with EF Core's change tracking mechanism and underlying database provider. EF Core translates object-oriented operations into relational database commands. Understanding the role of DbContext, Entity Tracking, and the purpose of each method (Add, Update, Remove, SaveChanges) is key to effectively managing data in EF Core applications.
Real-Life Use Case
Imagine an e-commerce application. When a user adds a product to their shopping cart, you'd use Add to insert a new record in the database representing the cart item. If the user updates the quantity of an item, you'd use Update. When the user removes an item, you'd use Remove. Finally, SaveChanges is called to persist all these changes to the database.
Best Practices
SaveChangesAsync over SaveChanges in web applications to prevent blocking threads.DbContext instances within a using statement to ensure proper disposal and avoid memory leaks.SaveChanges.SaveChanges calls in a try-catch block to handle potential database exceptions.context.Database.BeginTransaction()) to ensure atomicity.
Interview Tip
Be prepared to explain the difference between Add, Update, and Remove, and how they interact with SaveChanges. Also, understand the importance of using SaveChangesAsync in asynchronous environments. You might also be asked about disconnected entities and scenarios where Update is essential.
When to Use Them
Add, Update, and/or Remove operations and want to persist those changes to the database.
Alternatives
While EF Core provides a convenient way to interact with the database, alternative approaches exist:context.Database.ExecuteSqlRaw or context.Database.ExecuteSqlInterpolated. This gives you full control but requires more effort.
Pros
Cons
FAQ
-
What happens if `SaveChanges` fails?
If
SaveChangesfails (e.g., due to a database constraint violation or a network issue), an exception will be thrown. Any changes made within theDbContextwill be rolled back, preventing data corruption. It's important to wrapSaveChangesin atry-catchblock to handle potential exceptions. -
Does EF Core automatically detect all changes?
EF Core automatically detects changes to tracked entities. However, if you're working with detached entities (entities that were not originally retrieved from the
DbContextor were serialized/deserialized), you might need to explicitly callUpdateto mark the entity as modified. -
How can I improve the performance of `SaveChanges`?
- Only load the data you need: Use projections (
Select) to retrieve only the necessary columns. - Disable change tracking when not needed: Use
AsNoTracking()when querying data that you don't intend to modify. - Batch updates: For large numbers of updates, consider using techniques like bulk insert/update libraries.
- Optimize database indexes: Ensure that your database indexes are properly configured.
- Only load the data you need: Use projections (