Entity Framework Core Save Changes to the database using the SaveChanges method of DbContext. When we use the SaveChanges it prepares the corresponding insert
, update
, delete
queries. It then wraps them in a Transaction and sends them to the database. If any of the queries fails all the statements are rolled back. The Context also manages the entity objects during run time, which includes populating objects with data from a database, change tracking, etc.
Source Code:
The source code of this project is available in GitHub. It also contains the script of the database
Table of Contents
DbContext
The DbContext
is primarily responsible for managing the entities.
- It transforms the Entity Framework Core Queries to SQL Queries and sends it to the database.
- The Context translates the database results back to entities. we call this process as the materialization
- It allows us to create new entities, by adding them to the context
- Keep track of the changes made to the entities using ChangeTracker
- Save changes made to the entities in the database. By calling the
SaveChanges
method.
SaveChanges
The SaveChanges
method of the DbContext
save changes to the made to the entities to the database. The following example shows how to add, modify & remove data using the SaveChanges
method
Add Record
Create a new entity and use the Add
method to add the entity to the context. You can then call the SaveChanges
to persist the data to the database.
1 2 3 4 5 6 7 8 9 10 11 12 13 | using (EFCoreContext db = new EFCoreContext()) { Department department = new Department(); department.Name = "Secuirty"; db.Departments.Add(department); db.SaveChanges(); Console.WriteLine("Department {0} ({1}) is added ", department.Name, department.DepartmentID); } |
Update Record
Query and get the entity to, which you want to modify. Make the necessary changes and call the SaveChanges
1 2 3 4 5 6 7 8 9 10 | using (EFCoreContext db = new EFCoreContext()) { department = db.Departments.Where(d => d.Name == "Secuirty").First(); department.Descr = "This is Secuirty Department"; db.SaveChanges(); Console.WriteLine("Department {0} ({1}) is Updated ", department.Name, department.DepartmentID); } |
Delete Record
Similarly, use the Remove
method to mark the entity for deletion. Calling the SaveChanges
will delete the entity from the database
1 2 3 4 5 6 7 8 9 10 11 | using (EFCoreContext db = new EFCoreContext()) { department = db.Departments.Where(d => d.Name == "Secuirty").First(); db.Departments.Remove(department); db.SaveChanges(); Console.WriteLine("Department {0} ({1}) is Deleted ", department.Name, department.DepartmentID); } |
Multiple Operations in a Single Save Changes
We can combine multiple Add/Update/Remove operations and invoke save changes at the end to commit all of them together.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | using (EFCoreContext db = new EFCoreContext()) { Department department = new Department(); department.Name = "Secuirty"; db.Departments.Add(department); Department department = new Department(); department.Name = "Finance"; db.Departments.Add(department); db.SaveChanges(); } using (EFCoreContext db = new EFCoreContext()) { //Add Department department = new Department(); department.Name = "HR"; db.Departments.Add(department); Department department = new Department(); department.Name = "Production"; db.Departments.Add(department); //Update department = db.Departments.Where(d => d.Name == "Finance").First(); department.Name="Finance & Audit" //Remove department = db.Departments.Where(d => d.Name == "Secuirty").First(); db.Departments.Remove(department); // Save Everything db.SaveChanges(); } |
Call to SaveChanges runs under a single transaction. That is if one of the operations fails, all operations are is rolled back,
Connected & Disconnected Scenarios
The SaveChanges
method of the DbContext
prepares the Insert
, Update
& Delete
Queries. It does so by tracking the changes to each of the entities’ Context is tracking.
Whenever we query the database for entities, the Context retrieves them and mark the entity as Unchanged
. The ChangeTracker property of the DbContext
keeps track of the entities. Whenever we make update/add or delete the entities it mark them as Updated
, Added
or Deleted
etc.
When we call the SaveChanges
method, it loops through all the entities checking for their states. Depending on their Entity States it prepares the Insert
,Update
or Delete
SQL statements. Before sending it to the database it wraps them inside a Single Transaction. It rollbacks all the changes if any of the statements fail.
But for the SaveChanges
to work, the Context must correctly mark the entity as Updated
, Added
or Deleted
etc. But if we close the context and make changes to the entity, those will not be tracked by the context. Hence we have two possibilities here.
- Connected Scenario
- Disconnected Scenario
Connected Scenario
A connected Scenario is when we do not close the context, during the lifetime of the entities.
If the context is open, then the ChangeTracker
can easily keep track of the changes made to the entities. It now knows which entity is added/modified or deleted. During the SaveChanges
method call, the Context generates the correct SQL query (insert, update or delete) depending on the state of the entity (added, modified, or deleted)
The Code below shows the SaveChanges
in Connected Scenario. First, we create the Context using the Using
statement. We then retrieve the Department
entity from the database. We then modify the Descr
property of the entity. We can also add a new entity, update the entity, and delete an entity. Finally, when we call the SaveChanges
method to persist the data back to the database. The entire operation takes place in the same context. We do not close or destroy the Context between the retrieval and saving of the entities.
1 2 3 4 5 6 7 8 9 10 | using (EFCoreContext db = new EFCoreContext()) { department = db.Departments.Where(d => d.Name == "Secuirty").First(); department.Descr = "This is Secuirty Department"; db.SaveChanges(); Console.WriteLine("Department {0} ({1}) is Updated ", department.Name, department.DepartmentID); } |
Disconnected Scenario
The connected scenario is not always possible in real-life apps.
For example, in a web application, the user requests for the
entity. We create a new instance of the context, fetch the data, and send the data back to the user. The Server will close the Context & disposes it. Now, when the user updates the Department
Department
entity and returns it back. Now we create a new instance of the context. This newly created context knows nothing about the
entity. It does not know whether it is a new entity or an existing entity, where the user has made modifications.Department
Here, when we call SaveChanges
it won’t update anything in the database. This is a Disconnected Scenario.
To update this entity we need to attach
the Department
to the context and inform it to mark its status as Modified
using the db.Entry
method. Now if we call SaveChanges, the context will send a update
query to the database.
The example code is shown below
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | Department department; //Disconnected Scenario using (EFCoreContext db = new EFCoreContext()) { Console.Clear(); department = db.Departments.Where(d => d.Name == "Purchase").First(); } department.Descr = "Purchase Department-Disconnected Scenario"; using (EFCoreContext db = new EFCoreContext()) { //Attach the entity and set its Entity State as Modified db.Entry(department).State = EntityState.Modified; db.SaveChanges(); } |
How to do as command below in ef core
UPDATE table1 SET filed1=’value1′,field1=’value2′ WHERE id=1 AND id2=4
ow to do as command below in ef core
UPDATE table1 SET filed1=’value1′,field1=’value2′ WHERE id=1 AND id2=4
“To update this entity we need to attach the Employee to the context and inform it to mark its status as Modified using the db.Entry method. Now if we call the SaveChanges, the context will send an update query to the database.”
In the paragraph above, where its written Employee, should be Department