首页 > 解决方案 > 实体框架 SaveChanges 是如何工作的?

问题描述

我试图了解 EF 如何通过代码中的对象操作创建数据库请求。我的测试场景很简单:

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

我的想法是测试 EF 如何处理事务。用正确的值更改 A 并用错误的值更改 B(非现有 FK) 我跟踪 SQL Server DB 中发生的事情。我执行代码并且数据库中没有任何变化,这是预期的。奇怪的是有两个独立的 SQL 请求,我不明白 EF 如何恢复第一个。

标签: c#entity-framework

解决方案


Entity Framework和代码都是EntityFramework core开源的。您可以在以下位置查看代码

  1. 实体框架 -链接
  2. 实体框架核心 -链接

如果您看到Save 方法的内部代码(粘贴下面的代码快照),那么您可以验证它是否在内部创建了一个事务,如果没有提供外部事务。

    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;
    }

因此,您的以下代码将在内部包装在您可以在 SQL Profiler 中验证的事务中。

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

但是,SQL 探查器不会开始记录事务,因此您需要在跟踪设置中进行配置。请参阅下面的 SQL 探查器新跟踪设置的屏幕截图,在这里,我检查了Show All events. 在Transaction显示该类别之后。您可以订阅Begin Tran,Commit TranRollback Tran事件来验证交易语句。当您将运行您的方案时,您可以看到应该记录 Begin 和 Rollback。在此处输入图像描述


推荐阅读