Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.01.16;
Скачать: CL | DM;

Вниз

Не выполняется весь набор операций в транзакции   Найти похожие ветки 

 
elshad_s ©   (2003-12-17 17:34) [0]

Например есть такой отрывок текста программы:

TADOConnection.BeginTrans;
try
{Операция_1,
Операция_2,
Операция_3}
TADOConnection.CommitTrans;
except
------

Под "Операция_1,2,3" подразумевается добавление записей в таблицы T1, T2 и T3 соответственно.

Проблема в том что, после TADOConnection.CommitTrans только итог "Операция_3" вностися в Базу данных (в таблицу T3) а результаты предыдущих операций игнорируются. То есть Commit действует только на последнюю операцию.

СУБД - SQL Server Desktop Edition
Провайдер - Microsoft OLE DB Provider for SQL Server

P.S. В Access 97 все работает нормально:)


 
sniknik ©   (2003-12-17 17:41) [1]

в MSSQL
можно так
try
ADOCommand.CommandText:=
"begin transaction "+
"Операция_1 "+
"Операция_2 "+
"Операция_3 "+
"commit transaction";
ADOCommand.Execute;
except
------
попробуй во всяком случае


 
elshad_s ©   (2003-12-17 18:22) [2]

Спасибо за ответ, но дело в том что, в моем конкретном случае нет возможности обьединения операций в одну комманду. Так как, то что добавляется в "Операция_2" зависит от результата предыдущей операции. По этому в блоке команд транзакции с начала выполняется INSERT Query(Операция_1), потом идут вычисления, а после уже идет 2-ой INSERT Query(Операция_2) и тд.


 
Silver Alex ©   (2003-12-17 18:30) [3]

значит первые две операции не прошли, надо проверять возвращаемое значение

TADOConnection.BeginTrans;
try
Операция_1.ExecProc;
if Операция_1.Parameters.ParamByName("@RETURN_VALUE").Value <>0 then
raise Exception.Create("Error");
...
TADOConnection.CommitTrans;
except
TADOConnection.RollbackTrans;
------


 
elshad_s ©   (2003-12-17 19:15) [4]

To Silver Alex

>>значит первые две операции не прошли, надо проверять возвращаемое значение

Дело как раз в том, что выполнив "Операция_1" я запускаю Select Query, в котором добавленная запись сидит - логически. Тоже самое происходит после "Операция_2" и "Операция_3". В заключении отдав команду CommitTrans, для физической записи, видим что в базе отражается только результат "Операция_3" все остальные данные теряются. Самое интересное то, что я проверял тоже самое в Access 97 и все проходило без всяких проблем.


 
Кщд   (2003-12-18 06:08) [5]

возможно дело в transisolation?


 
Shirson ©   (2003-12-18 08:30) [6]

Может, между операциями GO поставить?


 
Silver Alex ©   (2003-12-18 09:20) [7]

ну а @RETURN_VALUE что возвращает?если не 0 значит чего то там не сложилось.Попробуй вообще убрать транзакцию, что будет.Посмотри или в самих хранимых процедурах нет транзакций. Надо вобщем локализовать ошибку


 
elshad_s ©   (2003-12-18 11:03) [8]

To Silver Alex

>>ну а @RETURN_VALUE что возвращает?если не 0 значит чего то >>там не сложилось.Попробуй вообще убрать транзакцию, что >>будет.Посмотри или в самих хранимых процедурах нет >>транзакций. Надо вобщем локализовать ошибку

Ну я же говорил... после каждой операции я использую результат. По этому если бы проблема была в самой операции, то последующее вычисление это выявило бы. А транзакцию убрать тоже проверял и все работает нормально. А хранимыми процедурами не пользуюсь.
Вот примерный текст программы

---------------------------------------------------------------- TADOConnection.BeginTrans;
try
Case MainForm.ActiveMDIChild.Tag of
23 : for_kod.Save;
......
......
......
end;
TADOConnection.CommitTrans;
except
TADOConnection.RollbackTrans;
raise;
end;
.....

procedure Tfor_kod.Save;
function myCalcFunc1 : String;
begin
Result := "Резальтат вычислений с добавленным значением поля iint в таблице T1"
end;
function myCalcFunc2 : String;
begin
Result := "Резальтат вычислений с добавленным значением поля code в таблице T2"
end;
begin
with Query_Save do
begin
Connection := TADOConnection;
Sql.Clear;
Sql.Add("INSERT INTO T1 (iint) Values (3)");
ExecSQL;

Sql.Clear;
Sql.Add("INSERT INTO T2 (code) Values (" + #39 + myCalcFunc1 + #39 + ")");
ExecSQL;

Sql.Clear;
Sql.Add("INSERT INTO T3 (code) Values (" + #39 + myCalcFunc2 + #39 + ")");
ExecSQL;
end;
end;
----------------------------------------------------------------

Вообше то я думаю может это проблема в самом СУБД, так как в Access"е проблем нет. Может это из за того, что у меня SQL Server Desktop Edition...


 
Scrooge   (2003-12-18 11:14) [9]

Такая же проблема была на MSSQL 7.0. Как лечить - не знаю, пришлось обходить, на 2000-м проблема исчезла.
ИМХО дело в СУБД.


 
elshad_s ©   (2003-12-18 11:24) [10]

То Scrooge

>>Такая же проблема была на MSSQL 7.0. Как лечить - не знаю,
>>пришлось обходить, на 2000-м проблема исчезла. ИМХО дело в СУБД

на 2000-м в смысле на SQL 2000? Если да то в каком edition"е?


 
KSergey ©   (2003-12-18 12:00) [11]

Не, дело не в версии и не в редакции сервера.
Тут что-то наверное не то.

А Sql - это что за компонент? А если вместо него использовать

ADOConnection.Execute(..), где использовать именно тот же ADOConnection, что и используется для транзакций?


 
Nikolay M. ©   (2003-12-18 12:16) [12]

А если пошаманить: делать не TADOConnection.BeginTrans (кстати, почему T ADOConnection?), а стартовать транзакцию руками первой командой:
Sql.Add("BEGIN TRANS");
?


 
elshad_s ©   (2003-12-18 12:46) [13]

To KSergey

>>Не, дело не в версии и не в редакции сервера.
>>Тут что-то наверное не то.

Я тоже так думаю. Так как в резултате данной проблемы про использовании транзакции можно забыть:( А такого не может быть что бы в SQL Server"е даже в какой то версии или редакции не было возможности полноценно пользоваться транзакциями.

>>А Sql - это что за компонент? А если вместо него использовать

А SQL это не компонента если ты судишь по отрывку из текста программы... Это свойство компоненты TADOQuery.

To Nikolay M.

>>кстати, почему TADOConnection?),

TADOConnection это просто мое лишнее желание представить его в смысле компоненты... Естественно что это в реале написано ИмяКомпоненты.BeginTrans;

>>а стартовать транзакцию руками первой командой:
>>Sql.Add("BEGIN TRANS");

И это проверял... вместо ADOConnection.BeginTrans писал Sql.Add("BEGIN TRANS"), а вместо ADOConnection.CommitTrans соответсвенно Sql.Add("COMMIT TRANS"). Результат был нулевым:(
А в самих операций(то есть перед и после INSERT"а) стартовать и коммитировать транзакцию нельзя потому что, все 3 операции это логическое единое целое. Транзакцию нужно стартовать в самом начале и кончать в самом конце.


 
JibSkeart ©   (2003-12-18 13:09) [14]

а смысл подобной операции ?
насколко я помню ,
MSSQL сам решит как ему лутьше обьеденить все это.


 
sniknik ©   (2003-12-18 13:13) [15]

попробуй всетаки мой вариант > sniknik © (17.12.03 17:41) [1]
(понимаю тебе так не пойдет, но попробуй)
а после того как так сработает,
подели на отдельные команды... желательно без извращений по минимуму, лутще всего 2 компонента на форме ADOConnection и ADOCommand
если и это сработает,
смотри что происходит на твоих запросах (вернее между ними), наверняка чтото случается вроде реконекта и т.д...


 
JibSkeart ©   (2003-12-18 13:17) [16]

да и необязательно реконект
явно гдето есть ошибка
и если есть хоть одна ошибка ,
то все что заключенно в
Begin trans
commit trans
не выполница тоесть произойдет откат

так что лутьше бы вы elshad_s
показали полный код что происходит
сдесь у вас
TADOConnection.BeginTrans;
try
{Операция_1,
Операция_2,
Операция_3}
TADOConnection.CommitTrans;
except


 
Silver Alex ©   (2003-12-18 13:25) [17]

очень странно все это. А если попробовать все это выполнить в хранимой процедуре?


 
JibSkeart ©   (2003-12-18 13:26) [18]

Это кстати тоже вариант.


 
MOA ©   (2003-12-18 13:32) [19]

Посмотрите всё-таки в Profiler, какие именно команды идут на сервер. Особенно обратите внимание - не создаётся ли дополнительный коннект(ы).
Удачи!


 
iSestrin   (2003-12-18 13:50) [20]

Все-таки, почему бы не поместить весь серверный код в хранимую процедуру и вызывать только ее?

судя по описанию:

>но дело в том что, в моем конкретном случае нет возможности обьединения операций в одну комманду. Так как, то что добавляется в "Операция_2" зависит от результата предыдущей операции. По этому в блоке команд транзакции с начала выполняется INSERT Query(Операция_1), потом идут вычисления, а после уже идет 2-ой INSERT Query(Операция_2) и тд.<

все прекрасно укладывается в одну процедуру.
серверу - серверово, клиенту - клиентово!


 
elshad_s ©   (2003-12-18 14:00) [21]

sniknik

>>попробуй всетаки мой вариант

Так это не как не подходит. Дело в том что, итог каждого INSERT"а влияет на то, что будет добавлена в следующем INSERT"е.

И вообще не может такого быть что бы, то что можно делать на Access"е не возможно было сделать на SQL Server"е!!!

To JibSkeart

>>да и необязательно реконект
>>явно гдето есть ошибка
>>и если есть хоть одна ошибка ,
>>то все что заключенно в
>>Begin trans
>>commit trans
>>не выполница тоесть произойдет откат

Да. Ты прав. Но проблема то и в том что, откат не происходит. В результате в базе имеем итог "Операция_3"(последная операция). А итоги предедущих операций игнорируются.

>>так что лутьше бы вы elshad_s
>>показали полный код что происходит
>>сдесь у вас

Более менее полный текст приведен на elshad_s © (18.12.03 11:03) [8]

To Silver Alex

>>А если попробовать все это выполнить в хранимой процедуре?

Хранимые процедуры не как не подходят так как программа многоплатформенная то есть должна работать на Access, SQL Server (а будушем:) и на Oracle)

Может вообше не с того конца беремся... Дело не в Delphi, не на коде а в настройках сервера или в параметрах...


 
AAron   (2003-12-18 14:01) [22]

Привет.

Собственно самое простое решение - посмотреть. Возьмите Profiler и увидете, какие реально запросы выполняются на базе данных, как организуется транзакция и т.п.

Все остальные кивки на версию SQL Server и т.п. можно не обращать внимания (пока).


 
elshad_s ©   (2003-12-18 14:05) [23]

To iSestrin

>>Все-таки, почему бы не поместить весь серверный код в хранимую
>>процедуру и вызывать только ее?

Дак прога же многоплатформенная...


 
Nikolay M. ©   (2003-12-18 14:09) [24]

Попробуй на время отказаться от функций:

with Query_Save do
begin
Connection := TADOConnection;
Sql.Clear;
Sql.Add("INSERT INTO T1 (iint) Values (3)");
ExecSQL;

Sql.Clear;
Sql.Add("INSERT INTO T2 (code) Values ( 4)");
ExecSQL;

Sql.Clear;
Sql.Add("INSERT INTO T3 (code) Values ( 5)");
ExecSQL;
end;


И каков смысл в строке
Connection := TADOConnection;
?


 
JibSkeart ©   (2003-12-18 14:10) [25]

А вообще я что то не вижу смысла за ключать все это в
begin trans
commit tran
может просто уберешь их пока да посмотри что получается


 
Silver Alex ©   (2003-12-18 14:12) [26]

возьми для чистоты эксперимента создай новый проект, положи на него TADOConnection, TADOQuery и также в транзакции просто вставь в те же таблички какие-нибудь записи.Посмотри что получится. И код бы глянуть полностью.


 
sniknik ©   (2003-12-18 14:20) [27]

elshad_s © (18.12.03 14:00) [21]
> sniknik
> >>попробуй всетаки мой вариант
> Так это не как не подходит. Дело в том что, итог каждого INSERT"а влияет на то, что будет добавлена в следующем
> INSERT"е.

я тебе не предлагаю менять программу а предлагаю методику(как сказано а ;о)) тестирования. чтобы знать где глюк. тебе чего на форму нового проэкта пару компонентов кинуть лень? и по кнопке 2 раза код переписать и выполнить?

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

> Да. Ты прав. Но проблема то и в том что, откат не происходит. В результате в базе имеем итог "Операция_3"(последная
> операция). А итоги предедущих операций игнорируются.
бред и голословные утверждения, без проверок и пояснений/доказательств. ничего не значат.
а повторять "не работает", в ответ на "проверьте это/посмотрите там", думаеш поможет?


 
sniknik ©   (2003-12-18 14:24) [28]

> И вообще не может такого быть что бы, то что можно делать на Access"е не возможно было сделать на SQL
> Server"е!!!
проверь
функции first, last, mid, sdate, dateserial......т.д.
линковка таблиц....
у самого аксеса формы, программирование интерфейса...
...
т.д.


 
ua-soft   (2003-12-18 14:31) [29]

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


 
elshad_s ©   (2003-12-18 14:47) [30]

To sniknik

Во первых спасибо за доброту:))) Что ты хочешь вместо меня решить проблему:))

Но у тебя условие что я должень сказать тебе как сделать и у тебя такой же глюк. Но это по моему мне не по силам:)
Все что я могу сделать это дать тебе кусок тестового проекта:

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, DB, ADODB, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
Edit1: TEdit;
ADOConnection1: TADOConnection;
ADOQuery1: TADOQuery;
Edit2: TEdit;
Edit3: TEdit;
Edit4: TEdit;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
ADOConnection1.BeginTrans;
try
with ADOQuery1 do
begin
SQL.Clear;
SQL.Add("INSERT INTO PRK (Kod, Ad, SAd, AAd)");
SQL.Add("VALUES (" + #39 + Edit1.Text + #39 + ",");
SQL.Add(#39 + Edit2.Text + #39 + ",");
SQL.Add(#39 + Edit3.Text + #39 + ",");
SQL.Add(#39 + Edit4.Text + #39 + ")");
ExecSQL;

SQL.Clear;
SQL.Add("INSERT INTO ADT (per_code)");
SQL.Add("VALUES (" + #39 + Edit1.Text + #39 + ")");
ExecSQL;
end;

ADOConnection1.CommitTrans;
except
ADOConnection1.RollbackTrans;
raise;
end;

end;

end.


Но если это же у тебя пройдет нормально, значит дело как я думаю не в тексте программы.

СУБД наверное уже знаеш какое... Не какие настройки не трогал. Устонавливал по схеме "Netx, Next, ... Finish"

ADOConnection соеденен через UDL файл.
Провайдер - Microsoft OLE DB Provider for SQL Server

>>проверь
>>функции first, last, mid, sdate, dateserial......т.д.
>>линковка таблиц....
>>у самого аксеса формы, программирование интерфейса...
>>...
>>т.д.

И ты думаеш что мне сейчас есть дело до каких то first, линковка, програмирование интерфейса.. и т.д.
Когда я говорил "И вообще не может такого быть что бы, то что можно делать на Access"е не возможно было сделать на SQL
Server"е!!!" я имел ввиду нечего кроме транзакции.


 
Nikolay M. ©   (2003-12-18 14:56) [31]

А транзакция-то вообще стартует? InTransaction после BeginTrans равно True? И что возвращает BeginTrans?


 
elshad_s ©   (2003-12-18 15:01) [32]

To Nikolay M.

>>А транзакция-то вообще стартует? InTransaction после
>>BeginTrans равно True? И что возвращает BeginTrans?

После BeginTrans InTransaction = True
После "Операция_1" InTransaction = True
После "Операция_2" InTransaction = True
После "Операция_3" InTransaction = True
После CommitTrans InTransaction = False


 
MOA ©   (2003-12-18 15:08) [33]

Ну посмотрите же наконец профайлером, что идёт на сервер!


 
Nikolay M. ©   (2003-12-18 15:14) [34]

Веришь-нет: у меня прекрасно все работает. Различие у нас с тобой только в одной строке:

dmMain.ADOConnection1.Connected := True;
dmMain.ADOConnection1.BeginTrans;
dmMain.q.SQL.Text := "INSERT INTO UpdateTest (val) VALUES (1)";
dmMain.q.ExecSQL;
dmMain.q.SQL.Text := "INSERT INTO UpdateTest (val) VALUES (2)";
dmMain.q.ExecSQL;
dmMain.q.SQL.Text := "INSERT INTO UpdateTest (val) VALUES (3)";
dmMain.q.ExecSQL;
dmMain.ADOConnection1.CommitTrans;


 
elshad_s ©   (2003-12-18 15:15) [35]

В Query Analyzer"е проверил:

Begin Transaction

INSERT INTO PRK (Kod, Ad, SAd, AAd) VALUES ("001", "ААА", "БББ", "ССС")
INSERT INTO ADT (per_code) VALUES ("001")

Commit Transaction

Здесь проблем нет:(
А вот если то же самое проделовать в проге, запись видна толко в таблице ADT!!!
Может что то есть в TADOConnection"е???


 
sniknik ©   (2003-12-18 15:16) [36]

> Все что я могу сделать это дать тебе кусок тестового проекта:
давно бы так.
хочеш сказать что вот это у тебя не работает? запись только в ADT.per_code ложится? а в PRK нет.
если так то :(( дело плохо. у меня работает.

единственное отличие что сделал это в таблицы (с теми же именами) добавил ключевое поле (у тебя оно есть? должно быть).

и ты не написал значение (важнного по моему) параметра ADOConnection1.KeepConnection (по умолчанию вроде true стоит).


 
elshad_s ©   (2003-12-18 15:19) [37]

To Nikolay M.

>>Веришь-нет: у меня прекрасно все работает. Различие у нас с
>>тобой только в одной строке:
>>
>>dmMain.ADOConnection1.Connected := True;

Ну это естественно... Я это делал в дизайн-тайме:) И в свойство ADOQuery.Connection выбрал ADOConnection1;


 
Dankov   (2003-12-18 15:28) [38]

Попробуй сделать следующее:

ADOConnection1.Properties.Item["Multiple connections"].Value:=False;

это надо сделать сразу же после ADOConnection1.Connected := True;


 
sniknik ©   (2003-12-18 16:13) [39]

проверил в профайлере.., в обшем, есть различия старта транзакции при такой записи
ADOConnection1.BeginTrans;
и
при такой к примеру
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Add("BEGIN TRANSACTION");
ADOQuery1.ExecSQL;

(и правильно что я первым вариантом не пользуюсь ;о)))
и с завершением по другому но правильней наверное (буду так делать)
IF @@TRANCOUNT > 0 COMMIT TRANSACTION


 
Александр Иванов ©   (2003-12-18 16:17) [40]

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


 
Александр Иванов ©   (2003-12-18 16:17) [41]

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


 
elshad_s ©   (2003-12-18 16:50) [42]

To Александр Иванов

>>У меня создается впечатление, что после отправки первых
>>запросов не фиксируется транзакция и соответственно невозможно
>>селектом получить подтверждение добавления записи. Т.к.
>>реальное добавление записи произойдет после фиксирования
>>командой commit

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


 
Nikolay M. ©   (2003-12-18 19:34) [43]


> используя его(это соединение) можно получить в SELECT"е
> добавленную запись

На самом деле его можно получить и в другом коннекте через
SELECT * FROM table ( nolock)
Если по F8 проходить последовательно каждый инсерт, то что говорит такой запрос - добавляются ли записи до коммита, непосредственно сразу после вставки?
Возможно, проблема именно с коммитом транзакции? Место на винте закончилось, transaction log стал очень большой или еще что-то?
Структуру таблиц какая?
Может действительно какие-то траблы с identity внутри транзакции?


 
mikali   (2003-12-19 06:38) [44]

Результаты профайлера - в студию ! Сколько просить-то ?


 
KSergey ©   (2003-12-19 08:46) [45]

Я никак не пойму автора: ему дают всякие рекомендации, задают дополнительные вопросы, а он вот уперся "я все написал" - и все тут!
Где ответы на мои вопросы (которые уточняющие??)

"Не, дело не в версии и не в редакции сервера. Тут что-то наверное не то." - это не вопрос, это ремарочка!!!

А вот "ADOConnection.Execute(..), где использовать именно тот же ADOConnection, что и используется для транзакций?" - это уже вопрос.
Так же вопрос, заданный в личной переписке "А эти Query точно подключены к этому TADOConnection?" - аналогично, без ответа. Ни в письме я ответа ни прочитал, ни на форуме.

Такое впечатление, что для вас важно, чтобы внимание обратили. А не решение проблемы.

Еще, обратите внимание на св-ство ADOConnection.KeepConnection, которое должно стоять в True.
Иначе, возможно, между командами соединение действительно рвется.

Короче, давайте уже ответы, а не общие рассуждения.

И еще не понравилось ваше замечание насчет "кросплатформенности" - что-то не сильно ли это круто? Есть ли в том смысл?



Страницы: 1 2 вся ветка

Текущий архив: 2004.01.16;
Скачать: CL | DM;

Наверх




Память: 0.62 MB
Время: 0.022 c
7-49777
xghost
2003-11-04 09:41
2004.01.16
Проблема с hook


14-49768
ИМХО
2003-12-24 20:41
2004.01.16
Top 20 стран-халявщиков ПО


1-49567
Eagle Owl
2004-01-02 15:20
2004.01.16
Code Insight


14-49760
}|{yk
2003-12-22 17:44
2004.01.16
Кстати. А почему-таки умер С++Builder?


6-49671
Sadya
2003-11-14 11:26
2004.01.16
No such host known