NServiceBus 和 Entity Framework 导致异常 - 基础提供程序在打开时失败
NServiceBus and Entity Framework causes exception - The underlying provider failed on Open
我无法理解端点中的以下异常并对其进行故障排除。我在 SO 上看到很多关于这个错误的帖子,但没有问题反映了我们应用程序中的特定场景。
这 间歇性地发生 ,我之前试图通过为 Entity Framework 增加 连接和命令超时 来解决这个问题.
端点和数据库运行在同一台机器上。该错误不会经常发生,只有在较大的更新或删除时才会发生。
作为旁注,我在调试时经常得到 "The underlying provider failed on Open" 。我一直认为这是因为我在断点上花费了太多时间,当我继续时连接被关闭了。
我想问一下NServiceBus 端点 中using/injecting 和Entity Framework 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 的原因。
但是什么时候 DependencyLifecycle.InstancePerUnitOfWork 是使用 Entity Framework 的正确选项?
如何更好地调试此错误?
这里是异常,堆栈:
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 的,尽管早期版本表现出相同的行为。
感谢您的帮助。
John,当连接已经打开和关闭时也会出现此错误,也许这就是问题所在。但它似乎试图加入分布式事务,但在那里失败了。如果是在调试时,你调试了多长时间?可能是连接超时,它会重试打开已关闭的连接?你的连接超时是多少?你用什么交通工具? MSDTC 打开了吗?你知道它什么时候开始失败吗?是不同的消息还是相同的消息?
不确定你的 MyDbContext
行为如何,但我的行为总是这样:
public class MyDbContext : DbContext
{
public MyDbContext : base("MyConnectionString")
{
}
}
这样我就可以确保它选择了一个特定的连接字符串,而且我知道我不会忘记它,什么也不会。
我无法理解端点中的以下异常并对其进行故障排除。我在 SO 上看到很多关于这个错误的帖子,但没有问题反映了我们应用程序中的特定场景。
这 间歇性地发生 ,我之前试图通过为 Entity Framework 增加 连接和命令超时 来解决这个问题.
端点和数据库运行在同一台机器上。该错误不会经常发生,只有在较大的更新或删除时才会发生。
作为旁注,我在调试时经常得到 "The underlying provider failed on Open" 。我一直认为这是因为我在断点上花费了太多时间,当我继续时连接被关闭了。
我想问一下NServiceBus 端点 中using/injecting 和Entity Framework 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 的原因。
但是什么时候 DependencyLifecycle.InstancePerUnitOfWork 是使用 Entity Framework 的正确选项?
如何更好地调试此错误?
这里是异常,堆栈:
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 的,尽管早期版本表现出相同的行为。
感谢您的帮助。
John,当连接已经打开和关闭时也会出现此错误,也许这就是问题所在。但它似乎试图加入分布式事务,但在那里失败了。如果是在调试时,你调试了多长时间?可能是连接超时,它会重试打开已关闭的连接?你的连接超时是多少?你用什么交通工具? MSDTC 打开了吗?你知道它什么时候开始失败吗?是不同的消息还是相同的消息?
不确定你的 MyDbContext
行为如何,但我的行为总是这样:
public class MyDbContext : DbContext
{
public MyDbContext : base("MyConnectionString")
{
}
}
这样我就可以确保它选择了一个特定的连接字符串,而且我知道我不会忘记它,什么也不会。