在webapi+ef+sqlserver開發項目時,利用transcope實現應用層級的事務時,偶爾會報分佈式事務錯誤,並且很而復現,特別蛋疼。現將本身的解決方法初步整理下。web
分析緣由:搭建repository+ef框架時,在repository crud中寫了savechange,savechange自身包含事務功能。而代碼中又用transcope裏面嵌套幾個使用repository方法的service時,會報分佈式事務錯誤,我懷疑是事務嵌套引起的。sql
The underlying provider failed on EnlistTransaction.(ㄒoㄒ) 在 System.Data.Entity.Core.EntityClient.EntityConnection.EnlistTransaction(Transaction transaction) 在 System.Data.Entity.Core.Objects.ObjectContext.EnsureContextIsEnlistedInCurrentTransaction[T](Transaction currentTransaction, Func`1 openConnection, T defaultValue) 在 System.Data.Entity.Core.Objects.ObjectContext.EnsureConnection(Boolean shouldMonitorTransactions) 在 System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func`1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess) 在 System.Data.Entity.Core.Objects.ObjectQuery`1.<>c__DisplayClass7.<GetResults>b__5() 在 System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func`1 operation) 在 System.Data.Entity.Core.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption) 在 System.Data.Entity.Core.Objects.ObjectQuery`1.<System.Collections.Generic.IEnumerable<T>.GetEnumerator>b__0() 在 System.Data.Entity.Internal.LazyEnumerator`1.MoveNext() 在 System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
參照stackoverflow https://stackoverflow.com/questions/16020270/the-underlying-provider-failed-on-enlisttransaction-cannot-access-a-disposed-ob數據庫
Also - is it possible you have got nested transaction scopes, and some inner scope is being rolled back (disposed without calling complete)
for some reason? Due to how transaction scopes work, that would immediately doom the outer transaction(s), rolling them back immediately. – Marc Gravell
解決方法一:調整代碼架構,剔除transcope,在unitofwork中統一savechange,一次提交事務(須要保證一次請求中的service中使用的DbContext爲一個,用autofac依賴注入便可實現)。而不是在repository中savechange.api
解決方法二:將數據庫服務器設置成支持分佈式事務。(暫時不推薦,有些狀況不是真正的分佈式事務,是自個框架、代碼問題)服務器
https://bbs.csdn.net/topics/390682626/架構
# 在兩臺機器上開啓MSDTC【管理工具---組件服務---個人電腦「屬性」---MSDTC】
# 開啓SQL SERVER的分佈式事務支持【屬性---鏈接----最下面的複選框】
#服務中的:Distributed Transaction Coordinator 設置自動開啓
#服務中的數據庫代理服務:SQL Server Agent (MSSQLSERVER) 設置自動開啓
# 確保兩臺機器的135端口都開着【注意防火牆】
# 確保主機名能夠PING通,而且對應的IP是正確的【PING得通,但IP不正確則配置一下host文
件】
#確保SQL SERVER 代理服務開啓
#肯定在進程中能夠看到msdtc.exe進程若是看不到請在CMD下運行"net start msdtc"開啓服務
後正常框架