简体   繁体   English

实体框架SaveChanges如何工作?

[英]How entity framework SaveChanges works?

I try to understand how EF creates DB requests from object manipulations in code. 我试图了解EF如何通过代码中的对象操作创建数据库请求。 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. 我的想法是测试EF如何处理事务。 Change A with correct value and change B with wrong value (non existing FK) I track what happening in SQL Server DB. 用正确的值更改A,用错误的值更改B(不存在FK)我跟踪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. 奇怪的是,有两个独立的SQL请求,我不明白EF如何还原第一个请求。

Both Entity Framework and EntityFramework core code are open source. Entity FrameworkEntityFramework core代码都是开源的。 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. 如果看到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;
    }

So your below code will internally wrapped inside a transaction which you can validate in SQL Profiler.. 因此,下面的代码将内部包装在一个事务中,您可以在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. 但是,SQL事件探查器不会开始记录事务,因此您需要在跟踪设置中进行配置。 See the below screenshot of SQL profiler new Trace setting, here, I have checked Show All events . 请参见下面的SQL事件探查器新跟踪设置的屏幕截图,在这里,我已经选中了Show All events After that Transaction category is being displayed. 之后,将显示“ Transaction类别。 You can subscribe for Begin Tran , Commit Tran and Rollback Tran events to validate transaction statements. 您可以订阅Begin TranCommit TranRollback Tran事件以验证事务语句。 When you will run your scenario, you can see that Begin and Rollback should be logged. 运行方案时,可以看到应该记录开始和回滚。 在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM