2016-04-27 43 views
0

我無法理解和排除端點中的以下異常。我在這個錯誤上見過很多關於SO的文章,但沒有任何問題反映了我們應用程序中的具體情況。NServiceBus和Entity Framework導致異常 - 底層提供程序在打開時失敗

間斷性地發生,和我以前試圖通過對實體框架同時增加連接和命令超時來解決這個問題。

端點和數據庫在同一臺機器上運行。錯誤不會經常發生,只有在更大的更新或刪除時纔會發生。

作爲一個方面說明,我經常在調試時得到「底層提供程序在打開時失敗」。我一直相信這是因爲我在斷點上花費了太多時間,並且當我繼續時連接關閉。

我想問一下什麼最佳實踐是在NServiceBus端點中使用/注入實體框架DbContext最好是通過NSB的依賴注入來注入上下文嗎?像這樣:

public class ConfigureDependencyInjection : INeedInitialization 
{ 
    public void Customize(BusConfiguration configuration) 
    { 
     configuration.RegisterComponents(reg => 
     { 
      reg.ConfigureComponent<MyDbContext>(DependencyLifecycle.InstancePerCall); 
     }); 
    } 
} 

或者我應該不會使用這個,但根據需要,而不是實例化上下文:

using (var context = new MyDbContext()) { ... } 

是這裏處理的信息是一個單一的物理信息,非常簡單 - - 這就是我選擇DependencyLifecycle.InstancePerCall的原因。

但是,當使用Entity Framework時,DependencyLifecycle.InstancePerUnitOfWork是否正確?

如何更好地調試此錯誤?

這裏是例外,和堆棧:

The underlying provider failed on Open. 
The operation is not valid for the state of the transaction. 

at System.Transactions.TransactionState.EnlistPromotableSinglePhase(InternalTransaction tx, IPromotableSinglePhaseNotification promotableSinglePhaseNotification, Transaction atomicTransaction, Guid promoterType) 
at System.Transactions.Transaction.EnlistPromotableSinglePhase(IPromotableSinglePhaseNotification promotableSinglePhaseNotification, Guid promoterType) 
at System.Transactions.Transaction.EnlistPromotableSinglePhase(IPromotableSinglePhaseNotification promotableSinglePhaseNotification) 
at System.Data.SqlClient.SqlInternalConnection.EnlistNonNull(Transaction tx) 
at System.Data.SqlClient.SqlInternalConnection.Enlist(Transaction tx) 
at System.Data.ProviderBase.DbConnectionInternal.ActivateConnection(Transaction transaction) 
at System.Data.ProviderBase.DbConnectionPool.PrepareConnection(DbConnection owningObject, DbConnectionInternal obj, Transaction transaction) 
at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection) 
at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection) 
at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection) 
at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions) 
at System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry) 
at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry) 
at System.Data.SqlClient.SqlConnection.Open() 
at System.Data.Entity.Infrastructure.Interception.InternalDispatcher`1.Dispatch[TTarget,TInterceptionContext](TTarget target, Action`2 operation, TInterceptionContext interceptionContext, Action`3 executing, Action`3 executed) 
at System.Data.Entity.Infrastructure.Interception.DbConnectionDispatcher.Open(DbConnection connection, DbInterceptionContext interceptionContext) 
at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.<>c__DisplayClass1.<Execute>b__0() 
at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func`1 operation) 
at System.Data.Entity.Core.EntityClient.EntityConnection.Open() 
--- End of inner exception stack trace --- 
at System.Data.Entity.Core.EntityClient.EntityConnection.Open() 
at System.Data.Entity.Core.Objects.ObjectContext.EnsureConnection(Boolean shouldMonitorTransactions) 
at System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func`1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess) 
at System.Data.Entity.Core.Objects.ObjectQuery`1.<>c__DisplayClass7.<GetResults>b__5() 
at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func`1 operation) 
at System.Data.Entity.Core.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption) 
at System.Data.Entity.Core.Objects.DataClasses.EntityCollection`1.Load(List`1 collection, MergeOption mergeOption) 
at System.Data.Entity.Core.Objects.DataClasses.RelatedEnd.DeferredLoad() 
at System.Data.Entity.Core.Objects.Internal.LazyLoadBehavior.LoadProperty[TItem](TItem propertyValue, String relationshipName, String targetRoleName, Boolean mustBeNull, Object wrapperObject) 
at System.Data.Entity.Core.Objects.Internal.LazyLoadBehavior.<>c__DisplayClass7`2.<GetInterceptorDelegate>b__1(TProxy proxy, TItem item) 
at System.Data.Entity.DynamicProxies.JournalTransaction_4CAE8D09C8D2614F98562EAA87E63CE3B6D4E9A6DEC760505C0C7C7C42295ECE.get_TransactionItems() 

這是NSB 5.2.14,雖然早期版本顯示相同的行爲。

感謝您的幫助。

回答

0

約翰,這個錯誤也可能發生在連接已經打開和關閉時,也許這就是問題所在。但是,它似乎試圖參與分佈式交易,並在那裏失敗。如果是在調試時,您需要多長時間調試?可能是連接超時並重試打開一個關閉的連接?什麼是您的連接超時?你使用什麼交通工具? MSDTC在嗎?你有什麼想法,當它開始失敗?這是一個不同的信息還是相同的?

不知道你是MyDbContext的行爲,但我始終是這樣的:

public class MyDbContext : DbContext 
{ 
    public MyDbContext : base("MyConnectionString") 
    { 
    } 
} 

這樣,我要確保它選擇一個特定的ConnectionString,我知道我不會忘記它,並沒有什麼。

+0

是的,我的DbContext和你的一樣。我的連接超時是:連接超時= 180 ---調試時我總是很匆忙,所以我沒有發現錯誤。儘管如此,我不知道。即使它是本地數據庫,MSDTC也必須開啓嗎?爲什麼它不會失敗100%的時間,但只有3/100?感謝您的意見和建議。 – John

+0

僅當您使用SQL作爲持久性時,傳輸和您自己的數據(由EF訪問)位於同一個數據庫中,並且連接字符串完全相同時,您將不會使用MSDTC。當然如果你的傳輸或持久性不支持事務。 因此,基本上,使用MSMQ + SQL Server進行任何操作,都會使其成爲分佈式事務。交易經理只能管理他們自己的資源,所以2個交易經理意味着MSDTC。 –

相關問題