日期:2008-06-02  浏览次数:20530 次

对数据库的操作是少不了事务处理的,事务能保整数据完整性和有效性。 在nh中,使用Transaction对象对.net的事务对象(实现了IDbTransaction接口的对象)进行了包装。


在nh中,一个典型的事务处理是这样的(见ISession.cs的注释)
ISession sess = factory.OpenSession();
Transaction tx;
try {
   tx = sess.BeginTransaction();
   //do some work
   ...
   tx.Commit();
}
catch (Exception e) {
   if (tx != null) tx.Rollback();
   throw e;
}
finally {
   sess.Close();
}
事务对象由session的BeginTransaction取得,同时事务开始,如果执行顺利则提交事务,否则回滚事务。

先来看看事务对象的创建

public ITransaction BeginTransaction() {
   callAfterTransactionCompletionFromDisconnect = false;
   transaction = factory.TransactionFactory.BeginTransaction(this);
   return transaction;
}
很简单,直接调用事务工厂并开始事务。

public ITransaction BeginTransaction(ISessionImplementor session) {
   Transaction tx = new Transaction(session);
   tx.Begin();
   return tx;
}
构造一个事务对象,并开始事务。

//*** Transaction.cs 34行 ***

public void Begin() {
   try {
      IsolationLevel isolation = session.Factory.Isolation;
      if( isolation==IsolationLevel.Unspecified ) {
         trans = session.Connection.BeginTransaction();
      }
      else {
         trans = session.Connection.BeginTransaction( isolation );
      }
   }
   catch( Exception e ) {
     throw new TransactionException("Begin failed with SQL exception", e);
   }
   begun = true;
}
根据隔离级别启动一个事务,注意是从数据连接开始一个事务哦。
从上面可以看出nh对数据库事务的包装是十分简单的。

在这种典型的事务处理方法中,transaction依赖于一个特定的session对象, 因为session关闭时将断开数据连接,如果没有提交事务,那么事务是提交还是回滚是由具体的数据库决定的, 但无论怎样,事务都会结束。

这样的话就存在一个问题,在面向对象开发的情况下,可能有一个事务操作的多个步骤分散在不同的对象中,为了保证此事务操作的原子性,显然需要将session传递到各个步骤(方法)中,这样才能保证所有步骤都在一个session(事务)中处理。

在nh中,数据库事务的生命周期是可以长于session的生命周期的,就是说数据库事务不必依赖于一个特定的session对象,这看起来不错,我们不用再传递session对象了。注意,我这里指的是数据库事务(IDbTransaction)。

下面就来实现这种事务处理方法,代码如下:

ISessionFactoryImplementor sfe = factory as ISessionFactoryImplementor;
IDbConnection conn = sfe.OpenConnection();
IDbTransaction trans
try
   trans = conn.BeginTransaction(); // 开始事务,这里也可以设置事务隔离级别。

   ISession s = factory.OpenSession(conn);
   // do something
   // ...
   s.Close();

   ISession s2 = factory.OpenSession(conn);
   // do something
   // ...
   s2.Close();

   trans.Commit(); // 提交事务
catch (Exceptin ex) {
   if ( trans != null ) trans.Rollback(); // 回滚事务
   throw ex
}
finally{
   conn.CloseConnection(conn);
}
首先取得数据库连接,然后开始事务,接着创建会话处理业务操作,注意在创建会话的时候把数据加连接也传递了给去,这是必需的。上面代码中最值的注意的就是会话的Close操作了,这个操作在默认情况下是会关闭数据库连接的,在这里之所以没有关闭连接,是因为OpenSession操作有带一个连接的缘故。

下面来看看nh中的相关代码

public ISession OpenSession(IDbConnection connection) {
   return OpenSession(connection, interceptor);
}

public ISession OpenSession(IDbConnection connection, IInterceptor interceptor) {
   return OpenSession( connection, false, long.MinValue, interceptor );
}

private ISession OpenSession(IDbConnection connection, bool autoClose,
       long timestamp, IInterceptor interceptor) {
 &nb