2016-12-07 2 views
0

В наших тестах интеграции SQL Server мы завершаем тесты в TransactionScope, которые затем откатываем после каждого теста, чтобы поддерживать базу данных в согласованном состоянии.Postgres, Npgsql и тесты интеграции с использованием откатов

Использование Postgres (или, возможно, специально Npgsql) не представляется возможным, так как выбор за пределами отдельного соединения не может считывать незафиксированные данные (даже в том случае, если в незафиксированном транзакции).

Базовый сценарий упрощен ниже:

[Test] 
public void ImplicitEnlist() 
{ 
    var connectionString = ConnectionString + ";enlist=true"; 
    using (var scope = new TransactionScope()) 
    { 
     using (var conn = new NpgsqlConnection(connectionString)) 
     { 
      conn.Open(); 
      Assert.That(conn.ExecuteNonQuery(@"INSERT INTO data (name) VALUES('test')"), Is.EqualTo(1)); 
     } 
     using (var conn = new NpgsqlConnection(connectionString)) 
     { 
      // -> this is false 
      Assert.That(conn.ExecuteScalar(@"SELECT COUNT(*) FROM data"), Is.EqualTo(1)); 
     } 
     scope.Rollback(); 
    } 
} 

Может кто-нибудь поделиться, как люди приближаются к этим базам данных с Postgres?

+0

Зачем вам нужны отдельные соединения для испытаний? –

+0

Интеграционные тесты - это очень широкие функциональные тесты и отключены от того, как базовые классы используют соединения. –

+0

В контексте я изучаю жизнеспособность перехода с сервера sql на postgres, и это была первая проблема, с которой я столкнулся с нашим набором тестов. –

ответ

1

копипаст ответа от github issue:

Я действительно не думаю, что все должно работать так, как вы думаете. Когда вы открываете два соединения внутри одного TransactionScope, вы делаете распределенные транзакции. PostgreSQL имеет 2 разных соединения, каждый с prepared transaction. Теперь это не означает, что оба соединения знают друг о друге или что две подготовленные транзакции несколько связаны. И поскольку они еще не были зафиксированы, применяется изоляция транзакций, и каждое соединение не может видеть незафиксированные изменения другого.

Подводя итог, распределенные транзакции означают, что при вызове Complete() на TransactionScope протокол двухфазной фиксации будет использоваться для обеспечения фиксации обеих транзакций или отсутствия. Это не гарантирует, что участвующие транзакции каким-то образом знают друг друга.

Хотя я уверен, что так все работает, я не эксперт в распределенных транзакциях или подготовленных транзакциях PostgreSQL, поэтому я могу ошибаться. Я собираюсь закрыть это, но откроется снова, если вы сможете найти любую информацию, противоречащую тому, что я сказал.

0

Лучший способ для достижения этой цели, как представляется, используя точки сохранения (https://www.postgresql.org/docs/9.1/static/sql-rollback-to.html) - это то, как ActiveRecord реализует его с Postgres/MySQL (http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html)

После рыть дальше в этом, оказывается, мы были зависимы на SQL Server до сих пор. SQL Server 2008 (и .NET 3.5+) может обрабатывать несколько соединений в транзакции без необходимости продвижения MSDTC, если они не открыты одновременно - https://msdn.microsoft.com/en-us/library/ms172070(VS.90).aspx. В этом сценарии Postgres не имеет такого же поведения.

Мы закончили удаление нашей зависимости от транзакций для отката тестового состояния (в любом случае у которого были свои проблемы) и вместо этого используйте Respawn (https://github.com/jbogard/Respawn), которые вместо этого перезагружают db обратно в пустое состояние для нас.

Смежные вопросы