2016-04-27 79 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。 –

相关问题