【发布时间】:2014-08-07 03:25:38
【问题描述】:
通过查看 Breeze 源代码,我看到 ContextProvider 在最终调用 BeforeSaveEntities 之前打开了一个连接。
问题:我想知道这是什么原因?因为在某些情况下这会导致不必要的事务提升。下面的解释。
ContextProvider.cs:
private void OpenAndSave(SaveWorkState saveWorkState) {
OpenDbConnection(); // ensure connection is available for BeforeSaveEntities
saveWorkState.BeforeSave();
SaveChangesCore(saveWorkState);
saveWorkState.AfterSave();
}
EFContextProvider.cs:
protected override void OpenDbConnection() {
var ec = ObjectContext.Connection as EntityConnection;
if (ec.State == ConnectionState.Closed) ec.Open();
}
如果我们在事务中保存,如果在 BeforeSaveEntities 中创建另一个 DbContext 以在数据库中执行其他一些保存操作(例如审计或我们想做的任何其他工作)并尝试将其加入当前事务。
澄清我想说的话:
1) 在非微风场景中,以下代码不会将事务提升为分布式事务:
using(TransactionScope ts1 = new TransactionScope(TransactionScopeOption.Required))
{
using(TransactionScope ts2 = new TransactionScope(TransactionScopeOption.Required))
{
MyContext2.SaveChanges(); /* Opens & closes a connection */
ts2.Complete();
}
MyContext1.SaveChanges(); /* Opens & closes a connection */
ts1.Complete();
}
2) 用微风,如果我总结一下代码的操作顺序,我们得到:
// Breeze opens the connection
OpenDbConnection(); /* Opens a connection for the breeze context */
// Breeze creates a TransactionScope
using(TransactionScope ts1 = new TransactionScope(TransactionScopeOption.Required))
{
// BeforeSaveEntities is called
// In BeforeSaveEntities, we decide to create/update/delete some other entities,
// but want these operations to be part of the same transaction.
// So, we create our own context, do our work and save it with a TransactionScope.
using(TransactionScope tsInBeforeSaveEntities = new TransactionScope(TransactionScopeOption.Required))
{
// ISSUE IS HERE:
// The following code with cause the transaction to be promoted to a
// distributed transaction, because another connection is already open by breeze.
MyContextInBeforeSaveEntities.SaveChanges(); /* Opens & closes a connection */
tsInBeforeSaveEntities.Complete();
}
// BeforeSaveEntities terminates
// Breeze saves the changes & complete its transaction.
[BreezeContext].SaveChanges(); /* Uses the already open connection */
ts1.Complete();
}
如果 Breeze 在调用 BeforeSaveEntities 之前没有调用 OpenDbConnection(),我们就不会有提升事务的问题。
我防止事务提升的解决方法是在我覆盖 BeforeSaveEntities 时关闭并重新打开 Breeze 的连接,但这有点讨厌。
protected override bool BeforeSaveEntity(EntityInfo entityInfo)
{
ObjectContext.Connection.Close();
// Create my DbContext, my TransactionScope and call SaveChanges
ObjectContext.Connection.Open();
return base.BeforeSaveEntity(entityInfo);
}
【问题讨论】:
标签: entity-framework transactions breeze