Override ISession.BeginTranscation and ISession.Transaction

40 views
Skip to first unread message

SirSirAaron

unread,
Dec 1, 2012, 12:30:07 AM12/1/12
to nhu...@googlegroups.com
What is the best way to override ISession.BeginTranscation and ISession.Transaction?

I would like to wrap NHibernate's ITransaction with Rx to observe when transactions rollback and commit.

 public interface IObservableTransaction : ITransaction
    {
        IDisposable SubscribeToCommit(Action<ITransaction> actionOnCommit);
        IDisposable SubscribeToRollback(Action<ITransaction> actionOnRollBack);
    }

    public class ObservableTransaction : IObservableTransaction
    {
        private readonly ITransaction _transaction;
        private readonly Subject<ITransaction> _commitSubject = new Subject<ITransaction>();
        private readonly Subject<ITransaction> _rollbackSubject = new Subject<ITransaction>();

        public ObservableTransaction(ITransaction transaction)
        {
            _transaction = transaction;
        }

        public void Dispose()
        {
            _transaction.Dispose();
            _commitSubject.Dispose();
        }

        public void Begin()
        {
            _transaction.Begin();
        }

        public void Begin(IsolationLevel isolationLevel)
        {
            _transaction.Begin(isolationLevel);
        }

        public IDisposable SubscribeToCommit(Action<ITransaction> actionOnCommit)
        {
            return _commitSubject.Subscribe(actionOnCommit);
        }

        public void Commit()
        {
            _transaction.Commit();
            _commitSubject.OnNext(this);
            _commitSubject.OnCompleted();
            _rollbackSubject.OnCompleted();
        }

        public IDisposable SubscribeToRollback(Action<ITransaction> actionOnRollBack)
        {
            return _rollbackSubject.Subscribe(actionOnRollBack);
        }

        public void Rollback()
        {
            _transaction.Rollback();
            _rollbackSubject.OnNext(this);
            _commitSubject.OnCompleted();
            _rollbackSubject.OnCompleted();
        }

        public void Enlist(IDbCommand command)
        {
            _transaction.Enlist(command);
        }

        public void RegisterSynchronization(ISynchronization synchronization)
        {
            _transaction.RegisterSynchronization(synchronization);
        }

        public bool IsActive
        {
            get { return _transaction.IsActive; }
        }

        public bool WasRolledBack
        {
            get { return _transaction.WasRolledBack; }
        }

        public bool WasCommitted
        {
            get { return _transaction.WasCommitted; }
        }
    }

Oskar Berggren

unread,
Dec 1, 2012, 7:08:44 AM12/1/12
to nhu...@googlegroups.com
Have a look to the transaction factories - those are pluggable.

/Oskar


2012/12/1 SirSirAaron <theyell...@gmail.com>:
> --
> You received this message because you are subscribed to the Google Groups
> "nhusers" group.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/nhusers/-/tkW9xpGRxQoJ.
> To post to this group, send email to nhu...@googlegroups.com.
> To unsubscribe from this group, send email to
> nhusers+u...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/nhusers?hl=en.

SirSirAaron

unread,
Dec 2, 2012, 8:11:05 PM12/2/12
to nhu...@googlegroups.com
Right as always, Oksar. Thank you very much!

Here is my code if anyone is interested:

configuration.SetProperty(NHibernate.Cfg.Environment.TransactionStrategy, typeof(ObservableTranscationFactory).AssemblyQualifiedName);

    public class ObservableTranscationFactory : ITransactionFactory
    {
        private readonly AdoNetWithDistributedTransactionFactory _adoDistributedfactory = new AdoNetWithDistributedTransactionFactory();

        public void Configure(IDictionary props)
        {
            _adoDistributedfactory.Configure(props);
        }

        public ITransaction CreateTransaction(ISessionImplementor session)
        {
            return new ObservableTransaction(_adoDistributedfactory.CreateTransaction(session));
        }

        public void EnlistInDistributedTransactionIfNeeded(ISessionImplementor session)
        {
            _adoDistributedfactory.EnlistInDistributedTransactionIfNeeded(session);
        }

        public bool IsInDistributedActiveTransaction(ISessionImplementor session)
        {
            return _adoDistributedfactory.IsInDistributedActiveTransaction(session);
        }

        public void ExecuteWorkInIsolation(ISessionImplementor session, IIsolatedWork work, bool transacted)
        {
            _adoDistributedfactory.ExecuteWorkInIsolation(session, work, transacted);
        }
    }


[Test]
        public void Test1()
        {
            ISessionFactory sessionFactory = NHibernateInitializer.Initialize().BuildSessionFactory();
            int i = 0;
            using (ISession session = sessionFactory.OpenSession())
            using(ITransaction transaction = session.BeginTransaction())
            {
                ObservableTransaction observableTransaction = session.Transaction as ObservableTransaction;
                observableTransaction.SubscribeToRollback(x => i = 1);
                transaction.Rollback();
            }
            Assert.That(i == 1);
Reply all
Reply to author
Forward
0 new messages