Система смешивания. Операции с SqlTransactions - PullRequest
5 голосов
/ 25 октября 2009

Этим вечером я освежил свои знания, пытаясь преодолеть 4 года плохой практики программирования из-за компании, в которой я работал. Одна из вещей, на которую я недавно наткнулся, была System.Transactions. Прочитав о них за последние несколько часов, я думаю, что у меня есть адекватное понимание того, как они работают и почему вы хотите их использовать. Однако все примеры, на которые я смотрел, показывают, что встроенный T-SQL вызывается из транзакции.

Я в значительной степени использую хранимые процедуры исключительно при доступе к базе данных, и все существующие хранимые процедуры обернуты в свои собственные SqlTransactions. Вы знаете, используя «Begin Tran», а затем откат или фиксацию. Если сохраненный процесс вызывает другой сохраненный процесс, он также создает транзакцию, и коммит всплывает до тех пор, пока внешний не подтвердит или не откатится. Прекрасно работает.

Итак, теперь мой вопрос: если я хотел начать использовать System.Transactions в моем коде - для простых целей мониторинга последовательных задач базы данных, которые не могут быть вложены в одну хранимую процедуру - как это работает с существующей SqlTransactions у меня уже есть в моих сохраненных процедур?

Будет ли использование System.Transactions в моем коде просто добавить еще один уровень защиты, прежде чем он будет фактически зафиксирован, или потому что я явно фиксирую в своей SqlTransaction - будут ли данные сохраняться независимо от фиксации или отката в транзакции на основе кода

Ответы [ 2 ]

5 голосов
/ 19 октября 2016

Нет, транзакции System.Transactions и Sql не смешиваются.

И я цитирую «Не смешивайте их» из следующей статьи MSDN: https://msdn.microsoft.com/en-us/library/ms973865.aspx.

Транзакции Sql не участвуют во внешней Системе. Транзакции так, как вы хотите. Сбой транзакций Sql или откат не приведет к откату других действий в System.Transaction.


Этот пример показывает явления:

using (var tx = new TransactionScope())
{
    using (var con = new SqlConnection($"{connectionstring}"))
    {
        con.Open();

        using (var com = new SqlCommand($"set xact_abort on; begin transaction; INSERT INTO dbo.KeyValueTable VALUES ('value1', '{Guid.NewGuid()}'); rollback;", con))
        {
            // This transaction failed, but it doesn't rollback the entire system.transaction!
            com.ExecuteNonQuery();
        }

        using (var com = new SqlCommand($"set xact_abort on; begin transaction; INSERT INTO dbo.KeyValueTable VALUES ('value2', '{Guid.NewGuid()}'); commit;", con))
        {
            // This transaction will actually persist!
            com.ExecuteNonQuery();
        }
    }
    tx.Complete();
}

После запуска этого примера в пустом хранилище данных вы должны заметить, что записи из второй операции Sql действительно зафиксированы, когда структура кода C # подразумевает, что они не должны быть.


Проще говоря, вы не должны смешивать их. Если вы управляете несколькими Sql-транзакциями внутри приложения, вам просто нужно использовать System.Transactions. К сожалению, это будет означать удаление кода транзакции из всех ваших хранимых процедур, но, увы, это необходимо, поскольку в случае смешанной модели вы не можете гарантировать целостность ваших данных.

0 голосов
/ 25 октября 2009

Работает просто отлично, если ваши внутренние транзакции в хранимых процессах фиксируются, все будет зафиксировано Если один из них откатится назад, то все во внешнем транскатации откатится назад. Чистая магия :)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...