Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 2004.01.16;
Скачать: [xml.tar.bz2];

Вниз

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

 
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.



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

Форум: "Базы";
Текущий архив: 2004.01.16;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.57 MB
Время: 0.01 c
1-49540
DimaK
2003-12-29 12:02
2004.01.16
Два вопросика по FastReport


9-49378
Andy_
2003-06-30 07:09
2004.01.16
IMAGE MOVE


1-49608
Dimmu Borgir
2004-01-04 14:05
2004.01.16
Форму в компонент


1-49507
Quit
2004-01-03 13:49
2004.01.16
Сохранить и загрузить цвет в ini


1-49527
lipskiy
2003-12-17 23:13
2004.01.16
Прокрутка колесом мыши





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский