Форум: "Базы";
Текущий архив: 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