我正在大型应用程序中使用Nhibernate和TransactionScope。 该应用程序应该修改3个数据库并支持它们之间的分布式事务。 这是我每次想要在分布式事务中查询或执行数据库上的某些sql时调用的代码:
IDbConnection connection = new SqlConnection(connectionString);
connection.Open();
ISession session = SessionFactory.OpenSession(connection);
这是在执行必要的操作后调用的代码
IDbConnection sqlConnection = session.Connection;
if (sqlConnection != null && sqlConnection.State == ConnectionState.Open)
sqlConnection.Close();
session.Dispose();
当我执行update-insert-delete语句时,我还将代码包装在其中:
using (var transaction = session.BeginTransaction())
{ //code here
transaction.Commit();}
我认为这是非常标准的东西。 现在......我在这个使用块中执行这些操作:
using (TransactionScope scope = new TransactionScope())
{
//code here
scope.Complete();
}
我的问题是我的事务在启动后大约6秒被偶尔中止(Transaction.Current.TransactionInformation.Status变为中止)。
这是我的分销交易协调员的追踪:
pid=6296 ;tid=13300 ;time=04/17/2012-19:34:29.430 ;seq=1 ;eventid=TRANSACTION_MANAGER_STARTED_2 ;;"TM Identifier='(null) '" ;"MS DTC started with the following settings: Security Configuration (OFF = 0 and ON = 1): Network Administration of Transactions = 0, Network Clients = 1, Inbound Transactions = 1, Outbound Transactions = 1, Transaction Internet Protocol (TIP) = 0, XA Transactions = 0, MSDTC RPC Security = Mutual Authentication Required, Account = NT AUTHORITY\NetworkService, Firewall Exclusion = 0, Transaction Bridge Installed = 0, Filtering duplicate events = 1."
pid=6296 ;tid=13300 ;time=04/17/2012-19:34:29.430 ;seq=2 ;eventid=TRACE_SETTINGS ;;"TM Identifier='(null) '" ;"Trace Configuration (OFF = 0 and ON = 1): Tracing Of DTC = 1, Tracing Of Transactions = 1, Tracing Of Aborted Transactions = 1, Tracing Of Long-Lived Transactions = 1, Tracing Of All Transactions = 0, Max Limit on Memory Buffers = 0."
pid=6296 ;tid=11372 ;time=04/17/2012-19:35:19.496 ;seq=3 ;eventid=CHECKPOINTING_STOPPED ;;"TM Identifier='(null) '" ;"MSDTC is suspending the checkpointing of transactions due to lack of activity"
pid=6296 ;tid=11372 ;time=04/17/2012-19:35:19.496 ;seq=4 ;eventid=TRACING_STOPPED ;;"TM Identifier='(null) '" ;"MSDTC is suspending the tracing of long - lived transactions due to lack of activity"
pid=6296 ;tid=10520 ;time=04/17/2012-19:36:31.191 ;seq=5 ;eventid=TRACING_STARTED ;;"TM Identifier='(null) '" ;"MSDTC is resuming the tracing of long - lived transactions"
pid=6296 ;tid=10520 ;time=04/17/2012-19:36:31.212 ;seq=6 ;eventid=TRANSACTION_BEGUN ;tx_guid=5c61419a-eec2-49c1-aaa1-007645a72e32 ;"TM Identifier='(null) '" ;"transaction has begun, description :'user_transaction'"
pid=6296 ;tid=10520 ;time=04/17/2012-19:36:31.212 ;seq=7 ;eventid=RM_ENLISTED_IN_TRANSACTION ;tx_guid=5c61419a-eec2-49c1-aaa1-007645a72e32 ;"TM Identifier='(null) '" ;"resource manager #1001 enlisted as transaction enlistment #1. RM guid = 'b9290b2d-9e1d-43ed-a5f3-e417f9b17906'"
pid=6296 ;tid=8016 ;time=04/17/2012-19:36:36.141 ;seq=8 ;eventid=RECEIVED_ABORT_REQUEST_FROM_BEGINNER ;tx_guid=5c61419a-eec2-49c1-aaa1-007645a72e32 ;"TM Identifier='(null) '" ;"received request to abort the transaction from beginner"
pid=6296 ;tid=8016 ;time=04/17/2012-19:36:36.141 ;seq=9 ;eventid=TRANSACTION_ABORTING ;tx_guid=5c61419a-eec2-49c1-aaa1-007645a72e32 ;"TM Identifier='(null) '" ;"transaction is aborting"
pid=6296 ;tid=8016 ;time=04/17/2012-19:36:36.141 ;seq=10 ;eventid=RM_ISSUED_ABORT ;tx_guid=5c61419a-eec2-49c1-aaa1-007645a72e32 ;"TM Identifier='(null) '" ;"abort request issued to resource manager #1001 for transaction enlistment #1"
pid=6296 ;tid=8016 ;time=04/17/2012-19:36:36.219 ;seq=11 ;eventid=RM_ACKNOWLEDGED_ABORT ;tx_guid=5c61419a-eec2-49c1-aaa1-007645a72e32 ;"TM Identifier='(null) '" ;"received acknowledgement of abort request from the resource manager #1001 for transaction enlistment #1"
pid=6296 ;tid=8016 ;time=04/17/2012-19:36:36.219 ;seq=12 ;eventid=TRANSACTION_ABORTED ;tx_guid=5c61419a-eec2-49c1-aaa1-007645a72e32 ;"TM Identifier='(null) '" ;"transaction has been aborted"
有谁知道我做错了什么以及如何防止我的交易被中止? 提前谢谢。
更新1: 如果我在实例化transactionscope对象后立即打开2个数据库的2个会话,那么我得到上面的错误。如果我只打开一个数据库的会话,并且我稍后打开一个会话,其中一个会话,我得到以下错误:
The PROMOTE TRANSACTION request failed because there is no local transaction active.
当达到connection.Open()并且连接向第二个数据库开放时,会发生这种情况。
答案 0 :(得分:1)
不知道这是否有助于跨多个数据库我还没有在该场景中测试过此代码。以下是我处理交易的示例。
public interface ISessionManager : IDisposable
{
ISession Session { get; set; }
ISession GetSession();
}
public class SessionManager : ISessionManager
{
private readonly ISessionFactory _sessionFactory;
private TransactionScope _scope;
public SessionManager(ISessionFactory sessionFactory)
{
_sessionFactory = sessionFactory;
}
#region ISessionManager Members
public ISession Session { get; set; }
public ISession GetSession()
{
if (Session == null)
{
Session = _sessionFactory.OpenSession();
if (!CurrentSessionContext.HasBind(_sessionFactory))
{
_scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions {IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted});
Session.BeginTransaction(IsolationLevel.ReadCommitted);
CurrentSessionContext.Bind(Session);
}
}
Session = _sessionFactory.GetCurrentSession();
Session.FlushMode = FlushMode.Never;
return Session;
}
public void Dispose()
{
if (CurrentSessionContext.HasBind(_sessionFactory))
{
CurrentSessionContext.Unbind(_sessionFactory);
}
try
{
Session.Transaction.Commit();
_scope.Complete();
_scope.Dispose();
Session.Flush();
}
catch (Exception)
{
Session.Transaction.Rollback();
throw;
}
finally
{
Session.Close();
Session.Dispose();
}
}
#endregion
}