Откат DbTransaction.Commit, вызывающий сбои в коде? - PullRequest
1 голос
/ 17 августа 2011

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

Вот проблема, хотя, в коде есть подфункции, которые вызываются, такие как getThis или getThat, которые имеют функции execute () и queryDatabase ().Код продолжал вызывать ошибки в некоторых случаях (не во всех случаях), где он зависал при этом "execute" или "queryDatabase".По сути, я думаю, что это связано с тем, что код требует данных из этих команд queryDatabase, прежде чем изменения будут зафиксированы.

После удаления передачи указателя dataAccess на эти подфункции (таким образом, они не являются частью фиксации), внезапно код успешно проходит.

Как правильно использовать Commit (), или я должен просто избавиться от него и не использовать эти функции транзакции?Просто позвольте коду сделать все мгновенно?

Я даже не могу найти последнюю ошибку, просто еще один расплывчатый "параметр соединения нулевой" SystemArgumentNullException, который каким-то образом связан с тем, что он является транзакцией.

System.ArgumentNullException: Value cannot be null
Parameter name: connection
at Data.Database.PrepareCommand(DbCommand command, DbConnection connection)

Трудно опубликовать код, потому что он охватывает как минимум 20 различных файлов (да, оригинальный разработчик не знает KISS).

Ответы [ 4 ]

2 голосов
/ 17 августа 2011

Transaction.Connection будет иметь значение NULL после фиксации транзакции, что может быть причиной того, что для соединения установлено значение NULL, если код передает Transaction.Connection как ссылку на все подфункции.Транзакция не является владельцем соединения, поэтому ее нельзя передавать другим подфункциям.

Звучит так, как будто соединение передается повсюду.Лучшим способом было бы поместить соединение в блок using и размещать только команды, которым требуется это соединение, и связанную с ним транзакцию в блоке tht using.

Вот базовый шаблон:

using(DbConnection connection = ...)

{

    connection.Open();

    using(DbTransaction transaction = connection.BeginTransaction(...))

    {

        ... do stuff ...

        transaction.Commit();        

    } // transaction rolled back here if an Exception is thrown before the call to Commit()

} // connection closed here

Транзакции необходимы, если код сохраняется в нескольких таблицах / записях.Единицу работы нужно совершать целиком, а не частично.Один из способов избавиться от транзакций состоит в том, чтобы база данных управляла ими напрямую с помощью хранимой процедуры.BEGIN TRAN выполняется явно в хранимой процедуре, в этот момент код C # больше не управляет им.

Также взгляните на пространство имен System.Transactions.Я думаю, что это проще в использовании, чем управление транзакциями на самом соединении.

1 голос
/ 17 августа 2011

Транзакция, как правило, должна использоваться для набора операций, которые логически представляют одну единицу работы.Другими словами, если в транзакции выполняются три действия и одно из действий завершается неудачно или вызывается откат, результат должен отражать, что none из трех действий фактически имело место в базе данных.

Поэтому, прежде чем вы решите удалить транзакцию, вам нужно будет определить намерения исходного разработчика и код (что может быть непросто!).Если действия должны завершиться успешно или потерпеть неудачу вместе, вам нужно будет продолжать использовать транзакцию.Если каждое действие может быть успешным или неудачным само по себе, вы, вероятно, можете полностью избавиться от транзакции, так как большинство баз данных имеют неявные транзакции для отдельных вызовов.

Несколько правил: 1. транзакции дорогиеначать их как можно позже и совершить их как можно раньше;2. часто (не всегда) не нужно, чтобы операции чтения / запросы попадали в транзакцию, включающую записи.

Операции с базой данных

1 голос
/ 17 августа 2011

После того, как объект транзакции DbTransaction.Commit () / Rollback () переходит в состояние «зомби».Если вы планируете продолжать использовать некоторые команды вне области транзакции, их необходимо отсоединить от транзакции, установив для свойства Transaction значение null

0 голосов
/ 17 августа 2011

Как правильно использовать Commit () или я должен просто избавиться от него и не использовать эти функции транзакции?Просто позвольте коду сделать все мгновенно?

Не избавляйтесь от транзакций.Они имеют смысл именно для того, чтобы обеспечить согласованность ваших данных.

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