To SaveChanges or not to SaveChanges?

by Kenji Elzerman
To SaveChanges or not to SaveChanges - Kens Learning Curve

When I started my tutorial about the Repository Pattern I knew a particular question would be asked: Why not call Entity Framework SaveChanges in the repository after each create, update, or delete? You could do that, but there is a theory about not doing that.

A Bit Of Context

Entity Framework is perfect for letting your application communicate with (almost) all kinds of data sources. You can create, delete, get, and update data using this framework. But, if you simply want to create new data nothing will happen. You need to commit the changes to the data source. You do this with SaveChanges(Async).

For the sake of clarity, I will be using ‘database’ instead of ‘data source’. This is because it makes a little bit easier to understand what I am trying to say.

So If I execute the following code:

dataContext.Movies.Add(movie);

Nothing will happen. The new movie is not added to the database. To make Entity Framework commit the chances (write) I need to change the code to this:

dataContext.Movies.Add(movie);
dataContext.SaveChanges();

This is perfectly normal and not something you should lay awake from at night. But I will become a nuisance when you forget it and search for ages for a bug, which isn’t there.

Behind the scenes of Entity Framework, the SaveChanges creates a transaction of all the create, updates, and deletes that are pending. If you call this method after each of these actions, you will have a lot of transactions.

The Repository SaveChanges

Now, look at the following code of a repository called MovieRepository and imagine I change the Create method to this:

public void Create(Movie movie)
{
    dataContext.Movies.Add(movie);
    dataContext.SaveChanges();
}

Each time this method is called, a new transaction is created and executed on the database. Now look at the following code in a class:

for (int i = 0; i< 10; i++)
{
    movieRepository.Create(new() { Title = $"Movie_{i}_Test" });
}

This code will create 10 transactions. A bit overkill, isn’t it?

To The Test

Let’s watch the output of the Web API with a SaveChanges each time a new movie is created. In other words: The method Create in the repository will call the SaveChanges, which is 10 times. This is the output:

Transactions - Entity Framework SaveChanges Or Not To SaveChanges - Kens Learning Curve

I couldn’t get them all on one screen, but I think you get the point.

Alright, let’s remove the SaveChanges from the repository method Create and call the SaveChanges AFTER the for-loop. This is the result:

One Transaction - Entity Framework SaveChanges Or Not To SaveChanges - Kens Learning Curve

Instead of seeing 10 transactions, now I just see 1. 

And this is just the very reason why I move the SaveChanges out of the methods Create, Update, and Delete.

Be careful though

Although this really saves time and communication with your database, you need to be careful. If you need to connect an entity to a new entity, but both don’t exist yet, you can run into problems.

Also, when you want to delete something you are better off committing that delete as soon as you can. If you don’t, other requests can still use an entity that is pending for deletion. The same goes for an update.

Think carefully when you want to commit a transaction to your database. Sometimes it’s better to do it right away, sometimes it’s better to put more queries in the queue.

My advice: Handle one type of entity and then call the SaveChanges. This way, other entities that may rely on the previous entity have new, updated data.

Not all support SaveChanges

If you are using the repository pattern without Entity Framework, which is possible, you might find that some data sources (yes, we are back at the data sources) don’t need a SaveChanges-method. When this happens I just leave the method blank. 

This is an approach that doesn’t break the business logic; the SaveChanges can still be called, but it just doesn’t do anything. But when I configure a repository that does need a SaveChanges I can implement the body of the SaveChanges-method in that repository.

Conclusion On Entity Framework SaveChanges

Well, that’s it actually. I hope this answers the question after reading the repository pattern in C# article.

If you have any questions, suggestions, or ideas about this approach; feel free to comment below. 

You may also like

Table Of Contents
Kens Learning Curve