Страница 1 из 2

Можно ли избежать неявной транзакции?

Добавлено: Ср 23 окт 2013 18:03
Rajoe
При выполнении ApplyUpdates компонента MSConnection самостоятельно сначала открывает транзакцию, затем по результатам либо фиксирует, либо откатывает. У меня довольно сложный процесс сохранения, который разбит на несколько частей, и все части должны быть заключены в транзакционные скобки. Но сделать это я не могу, так как уже первый ApplyUpdates завершает транзакцию. Можно ли как-то запретить MSConnection управлять транзакцией?

Re: Можно ли избежать неявной транзакции?

Добавлено: Чт 24 окт 2013 10:35
AndreyZ
На данный момент нет возможности избежать автоматической фиксации изменений при вызове метода TMSConnection.ApplyUpdates.
Мы добавили свойство TMSConnection.AutoCommit, это изменение войдет в следующий билд SDAC. Используя свойство AutoCommit, вы сможете контролировать фиксацию изменений следующим образом:

Код: Выделить всё

MSConnection1.AutoCommit := False;
// изменения
MSConnection1.ApplyUpdates;
// изменения
MSConnection1.ApplyUpdates;
MSConnection1.Commit;

Re: Можно ли избежать неявной транзакции?

Добавлено: Чт 24 окт 2013 14:54
Rajoe
Спасибо. А в этом случае использование StartTransaction не предполагается? Открываться транзакция будет по-прежнему автоматически?

Re: Можно ли избежать неявной транзакции?

Добавлено: Чт 24 окт 2013 15:19
AndreyZ
Вы можете контролировать старт транзакции вызовом метода TMSConnection.StartTransaction до вызова TMSConnection.ApplyUpdates . Если Вы не стартовали транзакцию, она будет автоматически запущена при первом вызове TMSConnection.ApplyUpdates .

Re: Можно ли избежать неявной транзакции?

Добавлено: Чт 24 окт 2013 15:51
Rajoe
Другими словами, она обязательно будет открыта, или мной через вызов StartTransaction, или автоматически из ApplyUpdates? То есть, отключить транзакцию вообще невозможно?

Re: Можно ли избежать неявной транзакции?

Добавлено: Пт 25 окт 2013 07:53
AndreyZ
Метод TMSConnection.ApplyUpdates отправляет изменения всех датасетов находящихся в режиме CachedUpdates на сервер. Транзакция обеспечивает корректное состояние базы данных. Если Вы хотите полностью управлять процессом отправки изменений датасетов на сервер, Вам следует использовать метод TMSQuery.ApplyUpdates вместо TMSConnection.ApplyUpdates. В данном случае транзакция не стартуется.

Re: Можно ли избежать неявной транзакции?

Добавлено: Пт 25 окт 2013 10:24
Rajoe
Понятно, спасибо. Попробую использовать TMSQuery.ApplyUpdates. Просто мне показалось нелогичным такое несимметричное управление транзакцией: транзакция открывается обязательно, а вот завершается или нет - ещё посмотрим. Если обновление данных выполняется достаточно сложной процедурой, внутри которой в зависимости от условий могут быть организованы разные транзакции или не организованы вовсе, то на уровне этой процедуры невозможно определить, кто начал транзакцию, клиент или сервер, соответственно, кто должен принять решение об её откате или фиксации. Это накладывает ненужные ограничения на алгоритмы и приводит к необоснованному усложнению разработки. На мой взгляд, логичнее было бы отключать не завершение транзакции, а всю транзакцию, то есть, если свойство, аналогичное AutoCommit, установлено, то и BEGIN TRANSACTION, и COMMIT/ROLLBACK генерируются компонентой. Если это свойство сброшено, то программист сам вызывает StartTransaction, Commit и Rollback в случае необходимости, или не использует транзакцию вовсе, обеспечивая целостность данных на уровне БД. При такой реализации ограничений нет.
Например, у меня многие хранимые процедуры (практически любая) могут быть вызваны как из клиента, так и из других процедур или скрипта. При этом транзакции контролируются следующим образом:

Код: Выделить всё

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);
При таком подходе процедура не в состоянии определить, начал ли транзакцию клиент, или вызывающая процедура, или скрипт, и своей транзакции не откроет. Тогда закрывать транзакцию обязательно придётся на стороне клиента, и механизм управления завершением транзакции с помощью AutoCommit становится бесполезен. Если отключение транзакции на стороне клиента будет полным, то такого не произойдёт, и серверные процедуры отработают правильно. Можно сказать - не используйте такой подход в хранимых процедурах - но бывают ситуации, когда только на уровне процедуры можно принять решение, открывать ли транзакцию и сколько.

Re: Можно ли избежать неявной транзакции?

Добавлено: Пн 28 окт 2013 14:24
AndreyZ
По умолчанию, SDAC стартует и фиксирует транзакцию. При использовании свойства TMSConnection.AutoCommit, Вы можете контролировать транзакцию сами. Но наличие транзакции при вызове TMSConnection.ApplyUpdates мы считаем необходимым, поскольку при этом гарантируется целостность данных на сервере.
Если Вы стартуете транзакцию в хранимой процедуре, Вам следует фиксировать или откатывать ее в этой же процедуре, независимо вызвана ли она другой процедурой или клиентом. Изменения которые были произведены в транзакции будут зафиксированы на сервере только при вызове COMMIT и @@TRANCOUNT = 1. Более подробную информацию Вы можете найти по следующей ссылке: http://technet.microsoft.com/en-us/libr ... 90295.aspx

Re: Можно ли избежать неявной транзакции?

Добавлено: Пн 28 окт 2013 16:44
Rajoe
Спасибо за ссылку, в курсе. Проблема не в том, чтобы правильно сохранить данные, а в том, чтобы сохранить их любой ценой. Вы заранее предполагаете бизнес-процесс, который должен быть правильным со всех сторон, и это работает в 95% случаев. Но бывают случаи, когда информация должна быть просто сохранена, с её корректностью будут разбираться потом отдельными методами. И это очень неудобно - несимметричное управление транзакцией. Я, если честно, никак не пойму смысла в отключении половины функциональности. То есть, программа местами не доступна для управления программисту, это усложняет работу, приходится искать обходные пути. Можно, конечно, в первой же строке хранимой процедуры написать rollback и дальше уже спокойно разбираться самому, но, согласитесь, это как-то странно выглядит, да и не всегда возможно. Очень, очень печально, что нельзя целиком управлять транзакцией.

Re: Можно ли избежать неявной транзакции?

Добавлено: Вт 29 окт 2013 09:14
AndreyZ
Метод TMSConnection.ApplyUpdates применяет множественные изменения сделанные в различных датасетах с помощью различных методов (выполнением SQL запросов, хранимых процедур и т.д.). Корректное поведение в данном случае является наличие транзакции. В противном случае, вызов 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: Можно ли избежать неявной транзакции?

Добавлено: Вт 29 окт 2013 11:41
Rajoe
Спасибо за терпение! :) Перевёл всё на ApplyUpdates наборов данных и сделал свою управляемую транзакцию, всё работает, как хотел.

Re: Можно ли избежать неявной транзакции?

Добавлено: Вт 29 окт 2013 12:12
AndreyZ
Я рад что смог помочь.

Re: Можно ли избежать неявной транзакции?

Добавлено: Чт 31 окт 2013 17:20
Rajoe
Всё же придётся ещё раз вернуться к этому вопросу. Что рекомендуется делать, если нужна распределённая транзакция?

Re: Можно ли избежать неявной транзакции?

Добавлено: Чт 31 окт 2013 17:40
AndreyZ
Что рекомендуется делать, если нужна распределённая транзакция?
Использовать компонент TMSTransaction. Подробную информацию Вы найдете здесь:
http://www.devart.com/sdac/docs/devart_ ... action.htm
http://www.devart.com/sdac/docs/work_tmstransaction.htm

Re: Можно ли избежать неявной транзакции?

Добавлено: Вт 05 ноя 2013 14:35
Rajoe
Спасибо.