Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How entity framework SaveChanges works?

I try to understand how EF creates DB requests from object manipulations in code. My test scenario is simple:

using(var context = new Context())
{
var entity = context.Entities.First();
entity.A = "TST";
entity.B = "WrongValue";
context.SaveChanges();
}

My idea is to test, how EF deal with transaction. Change A with correct value and change B with wrong value (non existing FK) I track what happening in SQL Server DB. I execute code and nothing change in DB, that was expected. Strange part is that there are two independant SQL request and I don't understand how EF revert first one.

like image 634
Krasi Nikolov Avatar asked Sep 17 '25 11:09

Krasi Nikolov


1 Answers

Both Entity Framework and EntityFramework core code are open source. You can check the code at

  1. Entity Framework - Link
  2. Entity Framework Core - Link

If you see the internal code of Save method (pasted the code snapshot below) then you can validate that it internally it creates a transaction if an external transaction is not provided.

    internal int SaveChangesInternal(SaveOptions options, bool executeInExistingTransaction)
    {
        AsyncMonitor.EnsureNotEntered();

        PrepareToSaveChanges(options);

        var entriesAffected = 0;

        // if there are no changes to save, perform fast exit to avoid interacting with or starting of new transactions
        if (ObjectStateManager.HasChanges())
        {
            if (executeInExistingTransaction)
            {
                entriesAffected = SaveChangesToStore(options, null, startLocalTransaction: false);
            }
            else
            {
                var executionStrategy = DbProviderServices.GetExecutionStrategy(Connection, MetadataWorkspace);
                entriesAffected = executionStrategy.Execute(
                    () => SaveChangesToStore(options, executionStrategy, startLocalTransaction: true));
            }
        }

        ObjectStateManager.AssertAllForeignKeyIndexEntriesAreValid();
        return entriesAffected;
    }

So your below code will internally wrapped inside a transaction which you can validate in SQL Profiler..

using(var context = new Context())
{
var entity = context.Entities.First();
entity.A = "TST";
entity.B = "WrongValue";
context.SaveChanges();
}

However, SQL profiler does not start logging transaction so you need to configure that in trace setting. See the below screenshot of SQL profiler new Trace setting, here, I have checked Show All events. After that Transaction category is being displayed. You can subscribe for Begin Tran, Commit Tran and Rollback Tran events to validate transaction statements. When you will run your scenario, you can see that Begin and Rollback should be logged. enter image description here

like image 172
user1672994 Avatar answered Sep 20 '25 00:09

user1672994