Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M [игнор отключен] [закрыт для гостей] / Ошибка при повторном сохранении после отката транзакции / 8 сообщений из 8, страница 1 из 1
20.08.2009, 11:46
    #36154218
Socratdv
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при повторном сохранении после отката транзакции
Наблюдаю интересную картину при повторном сохранении объекта после отката транзакции.
Наблюдается ошибка только при сохранении хранимых наследников. Причем сохранение проходит, но при этом генерируется ошибка %objlasterror.

Создаем два класса:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
Class TEST.TestClass Extends %Persistent
{

Property nowDate As %Date [ InitialExpression = {+$H} ];

}

Class TEST.TestClass2 Extends TEST.TestClass
{

}

Потом делаем так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
USER>s c=##class(TEST.TestClass2).%New()
 
USER>TSTART
 
TL1:USER>w c.%Save()
 1 
TL1:USER>TROLLBACK
 
USER>d c.%SetModified( 1 )
 
USER>TSTART
 
TL1:USER>w c.%Save()
 1 
TL1:USER>TCOMMIT
 
USER>w $SYSTEM.OBJ.DisplayError()
 
ОШИБКА # 5825 : Не является экземпляром TEST.TestClass21

Ошибка генерируется методом %OnDetermineClass при проверке id в методе %ExistsId ...
Вот такая вот интересная бага!
...
Рейтинг: 0 / 0
20.08.2009, 14:23
    #36154721
Ptn
Ptn
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при повторном сохранении после отката транзакции
Какой странный код ... а в чем смысл использовать объект после отката транзакции ?

Ваше отношение к %objlasterror - а именно его показывает без параметров $system.OBJ.DisplayError() тоже неясен

попробуйт написать программу :
Код: plaintext
1.
2.
3.
4.
	#include %occInclude
	new sc
	set sc=$$$ERROR( 5001 ,"Формируем сообщение об ошибке")
	quit   

выполните и потом сделайте $system.OBJ.DisplayError()...

В наличии сообщения об ошибки в %objlasterror, а точнее статуса, ничего странного не вижу...
...
Рейтинг: 0 / 0
20.08.2009, 14:34
    #36154757
Ptn
Ptn
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при повторном сохранении после отката транзакции
Собственно у вас при первом сохранени объекту назначается ID, объект вы не закрываете, ID не чистите.

Следовательно при повторном сохранении СУБД будет проверять данный ID на существование в виде объекта указанного класса - то бишь считывать объект и определять его classname.

В виду того что транзакцию вы откатили - естественно на этапе определения формируется ошибочный статус.

Но в виду того что объекта с данным ID нет - это не является ошибкой.

PS: Или я чего не понял ?
...
Рейтинг: 0 / 0
21.08.2009, 04:43
    #36155842
Socratdv
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при повторном сохранении после отката транзакции
PtnКакой странный код ... а в чем смысл использовать объект после отката транзакции ?
Смысл вполне разумный - если во время или после сохранения произошла ошибка, то необходимо откатить транзакцию, сообщить пользователю, чтобы он что-то исправил и потом снова попытаться сохранить. Думаю, это вполне логичный подход.
PtnВаше отношение к %objlasterror - а именно его показывает без параметров $system.OBJ.DisplayError() тоже неясен

Перед сохранением мы убиваем %objlasterror и потом после сохранения смотрим были ли ошибки в %objlasterror.
PtnВ наличии сообщения об ошибки в %objlasterror, а точнее статуса, ничего странного не вижу..
В наличии сообщения об ошибке в %objlasterror я тоже ни чего странного не вижу! Я считаю странным сам факт наличия ошибки в таком случае! По-моему, это не нормально, что в момент удачного сохранения генерируется ошибка %objlasterror - видать где-то чего-то не проверили, а именно в методе %ExistsId - надо бы сначала проверить, что существует узел с таким id, а потом проверять методом %OnDetermineClass , в таком случае ошибки бы не возникло.
...
Рейтинг: 0 / 0
21.08.2009, 04:58
    #36155844
Socratdv
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при повторном сохранении после отката транзакции
PtnСобственно у вас при первом сохранени объекту назначается ID, объект вы не закрываете, ID не чистите.
Не вижу смысла чистить ID после сохранения - ведь счетчик ID уже инкрементирован, просто отсутвует запись с таким ID - зачем еще раз инкрементировать счетчик и присваивать объекту новый ID?
PtnСледовательно при повторном сохранении СУБД будет проверять данный ID на существование в виде объекта указанного класса - то бишь считывать объект и определять его classname.

В виду того что транзакцию вы откатили - естественно на этапе определения формируется ошибочный статус.

Но в виду того что объекта с данным ID нет - это не является ошибкой.

PS: Или я чего не понял ?
Во время сохранения вызывается метод %ExistsId , который проверяет наличие данных в глобали с таким ID. Зачем генерировать ошибку при проверке, если данных нет? Попробуйте вызвать метод %ExistsId у класса наследника с ID, которого не существует - генерируется ошибка! Просто, как уже говорил, надо бы сначала проверить, что вообще существуют данные с таким ID, а потом уже определять класс. Вот как-то так...
...
Рейтинг: 0 / 0
21.08.2009, 09:10
    #36155951
Ptn
Ptn
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при повторном сохранении после отката транзакции
Socratdv
Смысл вполне разумный - если во время или после сохранения произошла ошибка, то необходимо откатить транзакцию, сообщить пользователю, чтобы он что-то исправил и потом снова попытаться сохранить. Думаю, это вполне логичный подход.

Да вполне логичный - но почему на протяжении всего этого времени объект остается открытый и ждет ввода пользователя - решительно не понятно.

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

SocratdvЯ считаю странным сам факт наличия ошибки в таком случае!

Да где Вы там ошибку то увидели ?

%Save() вам вернул 1

$SYSTEM.OBJ.DisplayError() вазращает вам _описание_ последнего соообщения об ошибке - которое о факте наличия ошибки не говорит ровно ничего, оно лишь говорить о том что кто то воспользовался API для формировать ошибочного %Status.

Вот вам пример когда существует метод для проверки записи в неком справочнике
Код: plaintext
1.
2.
3.
4.
CheckOperation(code) set code=$g(code)
 new SQLCODE
 &SELECT( select ID FROM SomeTable WHERE Code=:code)
 quit $S(SQLCODE= 0 :$$$OK, 1 :$$$ERROR( 5001 ,"Запись в справочнике SomeRefs с кодом "_code_" не определена"))

У меня есть две задачи:

Первая сделать новую запись в даный справочник по некому алгоритму

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
  set opcode= 330 
  if $$$ISERR(..CheckOperation(opcode)) {
   // Создаем опреацию  330  - автоматически генереруя необходимые алгоритму коды
   set sc=..AddOperation(opcode,"330-ть каждому")
   // Либо просто меняем операцию на следующую
   set opcode= 331 
 }
В этом коде не возникает ошибки, согласно алгоритму - но %objlasterror уже заполнен

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

Код: plaintext
1.
2.
3.
4.
5.
  set opcode= 330 
  set sc=..CheckOperation(opcode)
  if $$$ISERR(sc) {
    quit $$$ADDSC($$$ERROR( 5001 ,"Методу SomeMethod Требуется операция "_opcode),sc)
 }

В этом коде ошибка будет формироватся, согласно алгоритму - и %objlasterror так уже заполнен

Более того может быть и другой вариант - когда нужно трассировать ошибку по методу
Код: plaintext
1.
2.
3.
4.
5.
6.
  set contexterr=$$$ERROR( 5001 ,"Ошибка в методе Bla Bla Bla")
  /// а DeliverPayment может вернуть стандартное (Операционный день "2009-08-20" закрыт)
  set sc=..DeliverPayment("2009-08-20", 100 . 00 )
  if $$$ISERR(sc) {
    quit $$$ADDSC(contexterr,sc)
 }

В этом случае ошибки может и не быть - а %objlasterror будет заполнен
...
Рейтинг: 0 / 0
21.08.2009, 09:27
    #36155978
Ptn
Ptn
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при повторном сохранении после отката транзакции
Socratdv
Не вижу смысла чистить ID после сохранения - ведь счетчик ID уже инкрементирован, просто отсутвует запись с таким ID - зачем еще раз инкрементировать счетчик и присваивать объекту новый ID?

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

SocratdvПросто, как уже говорил, надо бы сначала проверить, что вообще существуют данные с таким ID, а потом уже определять класс. Вот как-то так...

Когда класс создает новый объект - он знает что он новый - назначает ему ID и тип класса не проверяет - ибо он достоверен.

Когда класс сохраняет уже не новый , а по всем параметрам СУБД считает его уже сохраненным, объект - то он не знает что его откатили - он _ОБЯЗАН проверить_ тип класса у используемого ID.

Откат транзакции не приводить объект в первоночальное "новое" состояние, поэтому ничего криминального в поведении кода нет. Тем более что %Save возращает вам 1-цу и объект таки сохраняет.

Но даже при этом %
...
Рейтинг: 0 / 0
21.08.2009, 09:36
    #36155992
Ptn
Ptn
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при повторном сохранении после отката транзакции
Socratdv
Перед сохранением мы убиваем %objlasterror и потом после сохранения смотрим были ли ошибки в %objlasterror.

Его имеет смысл смотреть только если Вам вернулась ошибка.

Точно так же как %msg имеет смысл смотреть только если у вас SQLCODE'=0
...
Рейтинг: 0 / 0
Форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M [игнор отключен] [закрыт для гостей] / Ошибка при повторном сохранении после отката транзакции / 8 сообщений из 8, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]