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
SaveChanges
fails (e.g., due to a database constraint violation or a network issue), an exception will be thrown. Any changes made within theDbContext
will be rolled back, preventing data corruption. It's important to wrapSaveChanges
in atry-catch
block 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
DbContext
or were serialized/deserialized), you might need to explicitly callUpdate
to 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 (