Можно ли избежать неявной транзакции?
Можно ли избежать неявной транзакции?
При выполнении ApplyUpdates компонента MSConnection самостоятельно сначала открывает транзакцию, затем по результатам либо фиксирует, либо откатывает. У меня довольно сложный процесс сохранения, который разбит на несколько частей, и все части должны быть заключены в транзакционные скобки. Но сделать это я не могу, так как уже первый ApplyUpdates завершает транзакцию. Можно ли как-то запретить MSConnection управлять транзакцией?
Re: Можно ли избежать неявной транзакции?
На данный момент нет возможности избежать автоматической фиксации изменений при вызове метода TMSConnection.ApplyUpdates.
Мы добавили свойство TMSConnection.AutoCommit, это изменение войдет в следующий билд SDAC. Используя свойство AutoCommit, вы сможете контролировать фиксацию изменений следующим образом:
Мы добавили свойство TMSConnection.AutoCommit, это изменение войдет в следующий билд SDAC. Используя свойство AutoCommit, вы сможете контролировать фиксацию изменений следующим образом:
Код: Выделить всё
MSConnection1.AutoCommit := False;
// изменения
MSConnection1.ApplyUpdates;
// изменения
MSConnection1.ApplyUpdates;
MSConnection1.Commit;
Re: Можно ли избежать неявной транзакции?
Спасибо. А в этом случае использование StartTransaction не предполагается? Открываться транзакция будет по-прежнему автоматически?
Re: Можно ли избежать неявной транзакции?
Вы можете контролировать старт транзакции вызовом метода TMSConnection.StartTransaction до вызова TMSConnection.ApplyUpdates . Если Вы не стартовали транзакцию, она будет автоматически запущена при первом вызове TMSConnection.ApplyUpdates .
Re: Можно ли избежать неявной транзакции?
Другими словами, она обязательно будет открыта, или мной через вызов StartTransaction, или автоматически из ApplyUpdates? То есть, отключить транзакцию вообще невозможно?
Re: Можно ли избежать неявной транзакции?
Метод TMSConnection.ApplyUpdates отправляет изменения всех датасетов находящихся в режиме CachedUpdates на сервер. Транзакция обеспечивает корректное состояние базы данных. Если Вы хотите полностью управлять процессом отправки изменений датасетов на сервер, Вам следует использовать метод TMSQuery.ApplyUpdates вместо TMSConnection.ApplyUpdates. В данном случае транзакция не стартуется.
Re: Можно ли избежать неявной транзакции?
Понятно, спасибо. Попробую использовать TMSQuery.ApplyUpdates. Просто мне показалось нелогичным такое несимметричное управление транзакцией: транзакция открывается обязательно, а вот завершается или нет - ещё посмотрим. Если обновление данных выполняется достаточно сложной процедурой, внутри которой в зависимости от условий могут быть организованы разные транзакции или не организованы вовсе, то на уровне этой процедуры невозможно определить, кто начал транзакцию, клиент или сервер, соответственно, кто должен принять решение об её откате или фиксации. Это накладывает ненужные ограничения на алгоритмы и приводит к необоснованному усложнению разработки. На мой взгляд, логичнее было бы отключать не завершение транзакции, а всю транзакцию, то есть, если свойство, аналогичное AutoCommit, установлено, то и BEGIN TRANSACTION, и COMMIT/ROLLBACK генерируются компонентой. Если это свойство сброшено, то программист сам вызывает StartTransaction, Commit и Rollback в случае необходимости, или не использует транзакцию вовсе, обеспечивая целостность данных на уровне БД. При такой реализации ограничений нет.
Например, у меня многие хранимые процедуры (практически любая) могут быть вызваны как из клиента, так и из других процедур или скрипта. При этом транзакции контролируются следующим образом:
При таком подходе процедура не в состоянии определить, начал ли транзакцию клиент, или вызывающая процедура, или скрипт, и своей транзакции не откроет. Тогда закрывать транзакцию обязательно придётся на стороне клиента, и механизм управления завершением транзакции с помощью AutoCommit становится бесполезен. Если отключение транзакции на стороне клиента будет полным, то такого не произойдёт, и серверные процедуры отработают правильно. Можно сказать - не используйте такой подход в хранимых процедурах - но бывают ситуации, когда только на уровне процедуры можно принять решение, открывать ли транзакцию и сколько.
Например, у меня многие хранимые процедуры (практически любая) могут быть вызваны как из клиента, так и из других процедур или скрипта. При этом транзакции контролируются следующим образом:
Код: Выделить всё
declare @iRes int, @bTrans bit;
if @@trancount = 0
begin
set @bTrans = 1;
begin transaction;
end
else
set @bTrans = 0;
set @iRes = 0;
--основной код с перехватом ошибок и установкой кода возврата в @iRes
if @bTrans = 1
begin
if @iRes < 0
rollback
else
commit;
end;
return(@iRes);
Re: Можно ли избежать неявной транзакции?
По умолчанию, SDAC стартует и фиксирует транзакцию. При использовании свойства TMSConnection.AutoCommit, Вы можете контролировать транзакцию сами. Но наличие транзакции при вызове TMSConnection.ApplyUpdates мы считаем необходимым, поскольку при этом гарантируется целостность данных на сервере.
Если Вы стартуете транзакцию в хранимой процедуре, Вам следует фиксировать или откатывать ее в этой же процедуре, независимо вызвана ли она другой процедурой или клиентом. Изменения которые были произведены в транзакции будут зафиксированы на сервере только при вызове COMMIT и @@TRANCOUNT = 1. Более подробную информацию Вы можете найти по следующей ссылке: http://technet.microsoft.com/en-us/libr ... 90295.aspx
Если Вы стартуете транзакцию в хранимой процедуре, Вам следует фиксировать или откатывать ее в этой же процедуре, независимо вызвана ли она другой процедурой или клиентом. Изменения которые были произведены в транзакции будут зафиксированы на сервере только при вызове COMMIT и @@TRANCOUNT = 1. Более подробную информацию Вы можете найти по следующей ссылке: http://technet.microsoft.com/en-us/libr ... 90295.aspx
Re: Можно ли избежать неявной транзакции?
Спасибо за ссылку, в курсе. Проблема не в том, чтобы правильно сохранить данные, а в том, чтобы сохранить их любой ценой. Вы заранее предполагаете бизнес-процесс, который должен быть правильным со всех сторон, и это работает в 95% случаев. Но бывают случаи, когда информация должна быть просто сохранена, с её корректностью будут разбираться потом отдельными методами. И это очень неудобно - несимметричное управление транзакцией. Я, если честно, никак не пойму смысла в отключении половины функциональности. То есть, программа местами не доступна для управления программисту, это усложняет работу, приходится искать обходные пути. Можно, конечно, в первой же строке хранимой процедуры написать rollback и дальше уже спокойно разбираться самому, но, согласитесь, это как-то странно выглядит, да и не всегда возможно. Очень, очень печально, что нельзя целиком управлять транзакцией.
Re: Можно ли избежать неявной транзакции?
Метод TMSConnection.ApplyUpdates применяет множественные изменения сделанные в различных датасетах с помощью различных методов (выполнением SQL запросов, хранимых процедур и т.д.). Корректное поведение в данном случае является наличие транзакции. В противном случае, вызов TMSConnection.ApplyUpdates может привести к не целостному состоянию данных.
Вы предлагаете добавить в SDAC функциональность которая нарушает основное правило множественных изменений: наличие транзакционных скобок. Мы не планируем вводить такую функциональность в SDAC.
Если Вы хотите избежать транзакции которую стартует метод TMSConnection.ApplyUpdates, Вам не следует его использовать. Например, Вы можете использовать следующий код:
Вы предлагаете добавить в SDAC функциональность которая нарушает основное правило множественных изменений: наличие транзакционных скобок. Мы не планируем вводить такую функциональность в SDAC.
Если Вы хотите избежать транзакции которую стартует метод TMSConnection.ApplyUpdates, Вам не следует его использовать. Например, Вы можете использовать следующий код:
Код: Выделить всё
var
i: integer;
ds: TCustomDADataSet;
begin
for i := 0 to MSConnection.DataSetCount - 1 do begin
ds := TCustomDADataSet(MSConnection.DataSets[i]);
if ds.UpdatesPending then
ds.ApplyUpdates;
end;
end;
Re: Можно ли избежать неявной транзакции?
Спасибо за терпение! Перевёл всё на ApplyUpdates наборов данных и сделал свою управляемую транзакцию, всё работает, как хотел.
Re: Можно ли избежать неявной транзакции?
Я рад что смог помочь.
Re: Можно ли избежать неявной транзакции?
Всё же придётся ещё раз вернуться к этому вопросу. Что рекомендуется делать, если нужна распределённая транзакция?
Re: Можно ли избежать неявной транзакции?
Использовать компонент TMSTransaction. Подробную информацию Вы найдете здесь:Что рекомендуется делать, если нужна распределённая транзакция?
http://www.devart.com/sdac/docs/devart_ ... action.htm
http://www.devart.com/sdac/docs/work_tmstransaction.htm