将 TransactionScope 与两个 DBContext 一起使用,出现错误
Using TransactionScope with two DBContext, get error
我有一个使用 TransactionScope
的函数。当我使用两个 dbContext
时,它崩溃了。错误信息是:
System.Data.EntityException: Error underlying provider Open. ---> System.Transactions.TransactionException: The operation is not valid for the state of the transaction. in System.Transactions.TransactionState.EnlistPromotableSinglePhase (InternalTransaction tx, IPromotableSinglePhaseNotification promotableSinglePhaseNotification, Transaction AtomicTransaction, Guid promoterType) in System.Transactions.Transaction.EnlistPromotableSinglePhase (IPromotableSinglePhaseNotification promotableSinglePhaseNotification, Guid promoterType) in System.Transactions.Transaction.EnlistPromotableSinglePhase (IPromotableSinglePhaseNotification promotableSinglePhaseNotification) in System .Data.SqlClient.SqlInternalConnection.EnlistNonNull (Transaction tx) in System.Data.SqlClient.SqlInternalConnection.Enlist (Transaction tx)
in System.Data.ProviderBase.DbConnectionInternal.ActivateConnection (Transaction transaction) in System.Data.ProviderBase.DbConnectionPool.PrepareConnection (DbConnection owningObject, DbConnectionInternal obj, Transaction transaction) in System.Data.ProviderBase.DbConnectionPool.TryGetConnection (DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout , allowCreate Boolean, Boolean onlyOneCheckConnection, DbConnectionOptions UserOptions, DbConnectionInternal & connection) in System.Data.ProviderBase.DbConnectionPool.TryGetConnection (DbConnection owningObject, TaskCompletionSource1 retry, DbConnectionOptions
UserOptions, DbConnectionInternal & connection) in
System.Data.ProviderBase.DbConnectionFactory.TryGetConnection (DbConnection
owningConnection, TaskCompletionSource1 retry, DbConnectionOptions UserOptions, DbConnectionInternal oldConnection, DbConnectionInternal & connection) in System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal (DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource1 retry, DbConnectionOptions UserOptions) in
System.Data.SqlClient.SqlConnection.TryOpenInner (TaskCompletionSource1 retry) in System.Data.SqlClient.SqlConnection.TryOpen (TaskCompletionSource`1 retry) in System.Data.SqlClient.SqlConnection.Open () in System.Data.EntityClient.EntityConnection. OpenStoreConnectionIf (Boolean openCondition, DbConnection storeConnectionToOpen, DbConnection originalConnection, String ExceptionCode, attemptedOperation String, Boolean & closeStoreConnectionOnFailure)
代码
public void example(int c, IEnumerable<int> pi, string comm)
{
using (var transactionScope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = IsolationLevel.RepeatableRead }))
{
var idsList = pi.ToList();
foreach (var playlist in Context.pl.Where(p => idsList.Contains(p.pid) && p.c== c&& p.stat== 1))
{
playlist.TimestampAuthorized = null;
var pl = "sss";
notif.generateNotifForUser((new Notification(1, 1, pl, 2, 2)));
}
Context.SaveChanges();
transactionScope.Complete();
}
}
问题出现在Context.SaveChanges()
;
如果我评论行 notif.generateNotifForUser();
它有效。进入那个功能,我也做 context.saveChanges();
谢谢
编辑:
似乎是通知方法导致了错误,因为它也在调用 Context.SaveChanges
您只需调用Context.SaveChanges
一次
我会删除通知方法中的 Context.SaveChanges
,只在事务范围结束时调用它一次。
// code before unchanged
foreach (var playlist in Context.pl.Where(p => idsList.Contains(p.pid) && p.c== c&& p.stat== 1).ToList()) // added ToList
// code after unchanged
这个问题与您试图为两件事使用开放连接这一事实有关。迭代 pl
DbSet 结果以及您在 generateNotifForUser
中所做的任何事情,这可能是您所在的位置 getting/doing 来自 DbContext 的其他内容(根据您的更新,您正在制作SaveChanges 调用 )。要修复此问题,请在 Lamda 语句的末尾添加 ToList
以强制在迭代开始之前立即完整地具体化查询结果。然后连接将不再打开,允许您在代码的其他部分继续使用 DbContext
。这还假设您没有在方法链的更下方犯类似的错误。
我有一个使用 TransactionScope
的函数。当我使用两个 dbContext
时,它崩溃了。错误信息是:
System.Data.EntityException: Error underlying provider Open. ---> System.Transactions.TransactionException: The operation is not valid for the state of the transaction. in System.Transactions.TransactionState.EnlistPromotableSinglePhase (InternalTransaction tx, IPromotableSinglePhaseNotification promotableSinglePhaseNotification, Transaction AtomicTransaction, Guid promoterType) in System.Transactions.Transaction.EnlistPromotableSinglePhase (IPromotableSinglePhaseNotification promotableSinglePhaseNotification, Guid promoterType) in System.Transactions.Transaction.EnlistPromotableSinglePhase (IPromotableSinglePhaseNotification promotableSinglePhaseNotification) in System .Data.SqlClient.SqlInternalConnection.EnlistNonNull (Transaction tx) in System.Data.SqlClient.SqlInternalConnection.Enlist (Transaction tx)
in System.Data.ProviderBase.DbConnectionInternal.ActivateConnection (Transaction transaction) in System.Data.ProviderBase.DbConnectionPool.PrepareConnection (DbConnection owningObject, DbConnectionInternal obj, Transaction transaction) in System.Data.ProviderBase.DbConnectionPool.TryGetConnection (DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout , allowCreate Boolean, Boolean onlyOneCheckConnection, DbConnectionOptions UserOptions, DbConnectionInternal & connection) in System.Data.ProviderBase.DbConnectionPool.TryGetConnection (DbConnection owningObject, TaskCompletionSource1 retry, DbConnectionOptions
UserOptions, DbConnectionInternal & connection) in
System.Data.ProviderBase.DbConnectionFactory.TryGetConnection (DbConnection
owningConnection, TaskCompletionSource1 retry, DbConnectionOptions UserOptions, DbConnectionInternal oldConnection, DbConnectionInternal & connection) in System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal (DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource1 retry, DbConnectionOptions UserOptions) in
System.Data.SqlClient.SqlConnection.TryOpenInner (TaskCompletionSource1 retry) in System.Data.SqlClient.SqlConnection.TryOpen (TaskCompletionSource`1 retry) in System.Data.SqlClient.SqlConnection.Open () in System.Data.EntityClient.EntityConnection. OpenStoreConnectionIf (Boolean openCondition, DbConnection storeConnectionToOpen, DbConnection originalConnection, String ExceptionCode, attemptedOperation String, Boolean & closeStoreConnectionOnFailure)
代码
public void example(int c, IEnumerable<int> pi, string comm)
{
using (var transactionScope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = IsolationLevel.RepeatableRead }))
{
var idsList = pi.ToList();
foreach (var playlist in Context.pl.Where(p => idsList.Contains(p.pid) && p.c== c&& p.stat== 1))
{
playlist.TimestampAuthorized = null;
var pl = "sss";
notif.generateNotifForUser((new Notification(1, 1, pl, 2, 2)));
}
Context.SaveChanges();
transactionScope.Complete();
}
}
问题出现在Context.SaveChanges()
;
如果我评论行 notif.generateNotifForUser();
它有效。进入那个功能,我也做 context.saveChanges();
谢谢
编辑:
似乎是通知方法导致了错误,因为它也在调用 Context.SaveChanges
您只需调用Context.SaveChanges
一次
我会删除通知方法中的 Context.SaveChanges
,只在事务范围结束时调用它一次。
// code before unchanged
foreach (var playlist in Context.pl.Where(p => idsList.Contains(p.pid) && p.c== c&& p.stat== 1).ToList()) // added ToList
// code after unchanged
这个问题与您试图为两件事使用开放连接这一事实有关。迭代 pl
DbSet 结果以及您在 generateNotifForUser
中所做的任何事情,这可能是您所在的位置 getting/doing 来自 DbContext 的其他内容(根据您的更新,您正在制作SaveChanges 调用 )。要修复此问题,请在 Lamda 语句的末尾添加 ToList
以强制在迭代开始之前立即完整地具体化查询结果。然后连接将不再打开,允许您在代码的其他部分继续使用 DbContext
。这还假设您没有在方法链的更下方犯类似的错误。