TransactionScope с базой данных SQLite в памяти и NHibernate - PullRequest
3 голосов
/ 20 марта 2011

Я столкнулся с проблемой, когда транзакция не откатывается при использовании TransactionScope.

Мы используем NHibernate с базой данных SQLite в памяти, поэтому мы ограничиваемся только одним подключением к БДв течение всего времени жизни приложения (в данном случае некоторые модульные тесты).

using (var ts = new TransactionScope(TransactionScopeOption.Required, 
                                     TimeSpan.Zero))
{
    using (var transaction = _repository.BeginTransaction())
    {
        _repository.Save(entity);
        transaction.Commit();
    }
    // ts.Complete(); <- commented Complete call still commits transaction
}

Даже если я удалю внутреннюю вложенную транзакцию NHibernate, поэтому код будет таким, как показано ниже, транзакция все еще фиксируется,

using (var ts = new TransactionScope(TransactionScopeOption.Required, 
                                     TimeSpan.Zero))
{       
    _repository.Save(entity);        
} // no Complete(), but the transaction still commits 

Ожидается ли недавно открытое соединение SQLite внутри блока TransactionScope, чтобы включить его в транзакцию?

Опять же, я не могу предоставить ему новое соединение, потому что это очистит базу данных.

Использование NHibernate 3.0 и SQLite 1.0.66.0, обеих последних версий на момент написания.

Примечание: использование transaction.Rollback() на объекте NHibernate ITransaction корректно откатывает транзакцию, просто поддержка TransactionScope не работает.

1 Ответ

1 голос
/ 20 марта 2011

Думаю, я нашел причину для этого.Если соединение не открывается изнутри блока TransactionScope, оно не будет зачислено в транзакцию.

Здесь есть некоторая информация: http://msdn.microsoft.com/en-us/library/aa720033(v=vs.71).aspx

Решение:

У меня уже был метод .BeginTransaction() в моем репозитории, поэтому я решил вручную подключить соединение к нему в транзакции окружения.

Это код, с которым я закончил:

    /// <summary>
    /// Begins an explicit transaction.
    /// </summary>
    /// <returns></returns>
    public ITransaction BeginTransaction()
    {
        if (System.Transactions.Transaction.Current != null)
        {
            ((DbConnection) Session.Connection).EnlistTransaction(System.Transactions.Transaction.Current);
        }
        return Session.BeginTransaction();
    }

А вот как я его использую:

  using (var ts = new TransactionScope(TransactionScopeOption.Required, TimeSpan.Zero))
  using (var transaction = repository.BeginTransaction())
  {
       repository.Save(entity);
       transaction.Commit(); // nhibernate transaction is commited
        // ts.Complete(); // TransactionScope is not commited
  } // transaction is correctly rolled back now
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...