在使用EF的时候,调用SaveChanges默认开启了事务。

            using (var ctx = new EFAppContext())
            {
                ctx.Teachers.Add(new Teacher { FirstName = "米高" });
                ctx.SaveChanges();
            }
SaveChanges默认会带上事务,SaveChanges的内部实现如下:
public virtual int SaveChanges(SaveOptions options)
{
	return SaveChangesInternal(options, executeInExistingTransaction: false);
}
 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;
        }
因为executeInExistingTransaction为false,所以流程进入SaveChangesToStore(options, executionStrategy, startLocalTransaction: true)
        private int SaveChangesToStore(SaveOptions options, IDbExecutionStrategy executionStrategy, bool startLocalTransaction)
        {
			......
				
            var entriesAffected
                = ExecuteInTransaction(
                    () => _adapter.Update(),
                    executionStrategy,
                    startLocalTransaction,
                    releaseConnectionOnSuccess: true);
			......
先看ExecuteInTransaction方法

connection.BeginTransaction()是重点,内部实现
 protected override DbTransaction BeginDbTransaction(IsolationLevel isolationLevel)
 {
   storeTransaction = executionStrategy.Execute(
                    () =>
                    {
						......

				return DbInterception.Dispatch.Connection.BeginTransaction(
				_storeConnection,interceptionContext);
                    });
	 ......
	_currentTransaction = new EntityTransaction(this, storeTransaction);
     return _currentTransaction;
 }

这里只是对EntityConnection里面的属性CurrentTransaction进行了赋值,这里太重要了,请记住EF里面所有关于事务的开启,关闭都和这个属性有关系

再看_adapter.Update方法最终实现


因为在前面初始化EntityTransaction,所以流程进入connection.CurrentTransaction.StoreTransaction,其中StoreTransaction属性在BeginDbTransaction的已经初始化了。到此SaveChanges内部开启事务的流程完毕

posted on 2021-05-07 15:22  zhourui  阅读(248)  评论(0编辑  收藏  举报