在使用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内部开启事务的流程完毕