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

Вниз

Как правильно "гасить" MSSQL-ошибку с кодом 266   Найти похожие ветки 

 
Bless ©   (2007-08-17 14:35) [0]

Как правильно отлавливать MSSQL-ошибку с кодом 266 (SeverityLevel=16) с текстом:
Transaction count after EXECUTE indicates that a COMMIT or ROLLBACK TRANSACTION statement is
missing. Previous count = %ld, current count = %ld

Мне нужно, чтоб в программе не выскакивало исключение с этой ошибкой. Где его правильнее всего гасить?
Заключать всякий ADOСommand.execute в try/except? Как-то некрасиво.
Мне кажется, что правильнее всего ловить ее где-то в событиях ADOConnection. Если я прав, то где именно?
Я пробовал в OnExecuteComplete так:

procedure TForm1.ADOConnection1ExecuteComplete
begin
if EventStatus=esErrorsOccured then
 if error.NativeError = 266 then
    EventStatus := esOK;
end;

но почему-то при error.Description =  "Transaction count after EXECUTE indicates that ..." (т.е. это та самая ошибка), error.NativeError почему-то равно 0, а не 266, соответственно, ошибка не гасится. Почему? Или это исключение надо ловить в другом месте?

А вот если ловить исключения в try/except, обрамляющим AdoCommand.execute, то там как и ожидалось error.NativeError=266.


 
Ega23 ©   (2007-08-17 15:37) [1]

Я бы не ADOСommand.execute в try/except заключал, а сделал бы 2 функции (процедуры):
procedure ADOOpen(ads:ADODataSet; ct : string ="*");
begin
 ads.Close;
 if ct<>"*" then ads.CommandText := ct;
 try
   ads.Open;
 except
   ..........
 end;
end;

и

procedure ADOExec(adc:ADOCommand; ct : string ="*");
begin
 if ct<>"*" then adc.CommandText := ct;
 try
   adc.Execute;
 except
   ..........
 end;
end;


и использовать их уже везде по проекту.


 
Bless ©   (2007-08-17 18:11) [2]

Можно и так, конечно. Только ведь нужно помнить о необходимости всегда вызывать эти обертки.
Поэтому, имхо, в ADOConnection это пихнуть красивше. Вот только непонятно почему NativeError=0. Хочу понять.

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


 
sniknik ©   (2007-08-18 09:13) [3]

> NativeError почему-то равно 0
это потому, что при выполнении тебе приходит не один результат, а от нескольких связанных рекордсетов. первый в списке судя по всему выполнился нормально вот и 0.
дальше уже ADODataSet перебирает рекордсеты в поисках значимого (NextRecordset), т.е. отсекая впереди стоящие "пустышки". он и генерирует ексепт при найденном в одном из них коде ошибки. т.е. ADOConnection там уже не при чем.

если у тебя первыми идут не возвращающие данные команды (они тоже посылают рекордсеты "пустышки", только ради кода выполнения/ошибки) то можеш от них избавится поставить SET NOCOUNT ON в начале скрипта, в процедурах оно само собой должно быть... (как у вас нет? тогда мы ... не идем к вам :), тогда возможно(зависит от скрипта) первым придет именно тот у которого ошибка и твой код в ADOConnection1ExecuteComplete сработает.
BEGIN TRANSACTION тоже посылает код завершения/рекордсет,
т.е. если в скрипте например 2 команды
BEGIN TRANSACTION  
SELECT * FROM ...
то SET NOCOUNT ON уберет первый пустой рекордсет и получишь при выполненом код сразу от второго
если же тоже две но
SELECT * FROM ...
SELECT * FROM ...
то в любом случае по очереди, и от второго только после "разбора".


 
Bless ©   (2007-08-20 08:50) [4]


> sniknik ©   (18.08.07 09:13) [3]


Мне кажется, ты невнимательно прочел.
Ничего из сказанного тобой не объясняет, почему при error.NativeError = 0
error.Description =  "Transaction count after EXECUTE indicates that ..."
т.е. ошибке с кодом 0 соответствует текст ошибки с кодом  266?

P.S. SET NOCOUNT ON стоит, про рекордсеты-пустышки я тоже в курсе (от тебя, кстати, спасибо :).


 
sniknik ©   (2007-08-20 09:09) [5]

> при error.NativeError = 0 error.Description =  "Transaction count after EXECUTE indicates that ..."
хм. действительно невнимательно, иначе бы это проверил... это стоит проверки. но теперь только после работы.


 
Bless ©   (2007-08-20 14:16) [6]

На всякий случай приведу простейший пример, иллюстрирующий проблему (вдруг пригодится).
Итак, есть хранимка
CREATE PROCEDURE [dbo].[vv]
AS
SET NOCOUNT ON
BEGIN TRAN
ROLLBACK TRAN


Есть проект с одной формой. На форме: один conn:TADOConnection с вбитой строкой подключения, один comm: TADOCommand, привязанный к conn и кнопка.
Обработчик OnClick для кнопки:

procedure TForm1.Button1Click(Sender: TObject);
begin
cmd.CommandText := "begin tran";
 cmd.Execute;
cmd.CommandText := "exec vv";
 cmd.Execute;
cmd.CommandText := "rollback tran";
 cmd.Execute;
end;


Обработчик OnExecuteComplete для conn:
procedure TForm1.connExecuteComplete(Connection: TADOConnection;
 RecordsAffected: Integer; const Error: Error;
 var EventStatus: TEventStatus; const Command: _Command;
 const Recordset: _Recordset);
begin
if error<>nil then
showmessage(IntToStr(error.NativeError) + " # " +
  error.Description);
end;


У меня нажатие на кнопку приводит к MessageBox-у с текстом

0 # Transaction count after EXECUTE indicates that a COMMIT or ROLLBACK TRANSACTION statement is missing. Previous count = 1, current count = 0.


 
Bless ©   (2007-08-20 14:18) [7]


> один comm: TADOCommand

ошибся. Правильно "один cmd: TADOCommand"


 
sniknik ©   (2007-08-20 16:31) [8]

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

что можно сказать. жалуйся в мелкософт,... или пользуйся Error.Number.


 
DiamondShark ©   (2007-08-21 13:37) [9]


> Bless ©   (20.08.07 14:16) [6]

А описание TSQL кто будет читать? Иван Фёдорович Крузенштерн?

ROLLBACK TRANSACTION without a savepoint_name or transaction_name rolls back to the beginning of the transaction. When nesting transactions, this same statement rolls back all inner transactions to the outermost BEGIN TRANSACTION statement. In both cases, ROLLBACK TRANSACTION decrements the @@TRANCOUNT system function to 0. ROLLBACK TRANSACTION savepoint_name does not decrement @@TRANCOUNT.


 
Bless ©   (2007-08-21 15:45) [10]


> sniknik ©   (20.08.07 16:31) [8]
> что можно сказать. жалуйся в мелкософт,... или пользуйся
> Error.Number.
>


Жаль. А я надеялся, что ты скажешь, что у меня просто MDAC старый :)


> DiamondShark ©   (21.08.07 13:37) [9]


Это к чему?


 
sniknik ©   (2007-08-21 16:01) [11]

> Жаль. А я надеялся, что ты скажешь, что у меня просто MDAC старый :)
прописать Number вместо NativeError гораздо проще чем переставить MDAC, циферки там только другие, непонятнее будут, но на это есть комментарии...


 
kaif ©   (2007-08-21 16:21) [12]

Вообще-то просто так гасить ошибки "чтобы не выскакивали" не есть хорошо, ИМХО.

А по сабжу я обычно перехватываю ошибки в Application.OnException, анализирую там класс ошибки с помощью оператора is, привожу явно с помощью оператора as к этому классу, в котором обычно есть свойство ErrorCode типа Integer, если это ошибка сервера баз данных, анализирую этот код в операторе типа case и дальше уже предпринимаю какие-то действия - обычно сообщаю юзеру об ошибке в понятной для него форме или делаю дополнительные запросы для выяснения причин и сообщения пользователю в еще более понятной для него форме. То есть у меня в Application.OnException прописана куча ифов и касов, вызывающих процедуры для существенных или информативных ошибок и некий ELSE, выдающий все остальное в виде просто текста E.Message.

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


 
DiamondShark ©   (2007-08-21 16:46) [13]


> Bless ©   (21.08.07 15:45) [10]
> Это к чему?

Если начистоту, то это к тому, что писать заведомо бредовый SQL, а потом искать способ подавить ошибку -- это редкая форма мазохизма.


 
Bless ©   (2007-08-22 12:23) [14]

> Если начистоту, то это к тому, что писать заведомо бредовый SQL, а потом искать способ
> подавить ошибку -- это редкая форма мазохизма.


Эта ошибка сервера с точки зрения моей логики ошибкой не является, поэтому она не должна ни выскакивать, ни обрабатываться, просто игнорироваться.
Внешняя транзакция и должна быть откачена в случае облома, я знаю о таком поведении, оно учтено в вызывающих хранимках и пока нигде не стало ни проблемой, ни сюрпризом.
Может, и не правильно идеологически, что хранимка откачивает чужие транзакции, но я не вижу причин менять то, что нормально работает.
Тем более, что альтернатива, как я ее себе представляю, тоже не лишена недостатков.
Заведомо НЕбредовый SQL - это пихать везде, где есть BEGIN TRAN, SAVEPOINT-ы, я правильно понял?
Если так, то, насколько я могу судить, это потребует применения жестких правил именования SAVEPOINT-ов, исключающих дублирование имен, исполнение которых возлагается на людей, пишущих хранимки. В противном случае раскиданные грабли будут могут больно стукнуть по лбу. А людям как раз свойственна забывчивость.
Или я не прав?



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

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

Наверх





Память: 0.5 MB
Время: 0.054 c
15-1195788241
Slider007
2007-11-23 06:24
2007.12.23
С днем рождения ! 23 ноября 2007 пятница


2-1196088119
Ivolg
2007-11-26 17:41
2007.12.23
Отправка файлов через сокеты


15-1195808646
Ega23
2007-11-23 12:04
2007.12.23
Где сейчас можно купиь 5 лицензий на


2-1196096385
AntonUSAnoV
2007-11-26 19:59
2007.12.23
импорт/экспорт в MS WORD


15-1195580908
master_asasin
2007-11-20 20:48
2007.12.23
Конференция





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский