entity-framework/core/saving/index.md
While querying allows you to read data from the database, saving data means adding new entities to the database, removing entities, or modifying the properties of existing entities in some way. Entity Framework Core (EF Core) supports two fundamental approaches for saving data to the database.
In many scenarios, your program needs to query some data from the database, perform some modification on it, and save those modifications back; this is sometimes referred to as a "unit of work". For example, let's assume that you have a set of Blogs, and you'd like to change the Url property of one of them. In EF, this is typically done as follows:
using (var context = new BloggingContext())
{
var blog = await context.Blogs.SingleAsync(b => b.Url == "http://example.com");
blog.Url = "http://example.com/blog";
await context.SaveChangesAsync();
}
The code above performs the following steps:
UPDATE to update the relevant rows.Note that the above described a typical update operation for existing data, but similar principles hold for adding and removing entities. You interact with EF's change tracker by calling xref:Microsoft.EntityFrameworkCore.DbSet`1.Add*?displayProperty=nameWithType and xref:Microsoft.EntityFrameworkCore.DbSet`1.Remove*, causing the changes to be tracked. EF then applies all tracked changes to the database when xref:Microsoft.EntityFrameworkCore.DbContext.SaveChanges is called (e.g. via SQL INSERT and DELETE when using a relational database).
xref:Microsoft.EntityFrameworkCore.DbContext.SaveChanges offers the following advantages:
For more information and code samples on basic xref:Microsoft.EntityFrameworkCore.DbContext.SaveChanges usage, see Basic SaveChanges. For more information on EF's change tracking, see the Change tracking overview.
While change tracking and xref:Microsoft.EntityFrameworkCore.DbContext.SaveChanges are a powerful way to save changes, they do have certain disadvantages.
First, xref:Microsoft.EntityFrameworkCore.DbContext.SaveChanges requires that you query and track all the entities you will be modifying or deleting. If you need to, say, delete all Blogs with a rating below a certain threshold, you must query, materialize and track a potentially huge number of rows, and have xref:Microsoft.EntityFrameworkCore.DbContext.SaveChanges generate a DELETE statement for each and every one of them. Relational databases provide a far more efficient alternative: a single DELETE command can be sent, specifying which rows to delete via a WHERE clause, but the xref:Microsoft.EntityFrameworkCore.DbContext.SaveChanges model doesn't allow for generating that.
To support this "bulk update" scenario, you can use xref:Microsoft.EntityFrameworkCore.RelationalQueryableExtensions.ExecuteDelete* as follows:
context.Blogs.Where(b => b.Rating < 3).ExecuteDelete();
This allows you to express a SQL DELETE statement via regular LINQ operators - similar to a regular LINQ query - causing the following SQL to be executed against the database:
DELETE FROM [b]
FROM [Blogs] AS [b]
WHERE [b].[Rating] < 3
This executes very efficiently in the database, without loading any data from the database or involving EF's change tracker. Similarly, xref:Microsoft.EntityFrameworkCore.RelationalQueryableExtensions.ExecuteUpdate* allows you to express a SQL UPDATE statement.
Even if you aren't changing entities in bulk, you may know exactly which properties of which entity you want to change. Using the change tracking API to perform the change can be overly complex, requiring creating an entity instance, tracking it via xref:Microsoft.EntityFrameworkCore.DbSet`1.Attach*, making your changes and finally calling xref:Microsoft.EntityFrameworkCore.DbContext.SaveChanges. For such scenarios, ExecuteUpdate and ExecuteDelete can be a considerably simpler way to express the same operation.
Finally, both change tracking and xref:Microsoft.EntityFrameworkCore.DbContext.SaveChanges itself impose a certain runtime overhead. If you're writing a high performance application, ExecuteUpdate and ExecuteDelete allow you to avoid both these components and efficiently generate the statement you want.
However, note that ExecuteUpdate and ExecuteDelete also have certain limitations:
Where clause to implement concurrency control yourself.For more information and code samples, see ExecuteUpdate and ExecuteDelete.
Following are a few guidelines for when to use which approach. Note that these aren't absolute rules, but provide a useful rules of thumb:
SaveChanges; it will automatically detect which changes need to be applied. Example scenarios:
SaveChanges; it will figure out the proper ordering of the changes and how to link everything together.
ExecuteUpdate and ExecuteDelete. Example scenarios:
ExecuteUpdate and ExecuteDelete. Example scenarios: