powered by simpleCommunicator - 2.0.59     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M [игнор отключен] [закрыт для гостей] / Ошибка при повторном сохранении после отката транзакции
8 сообщений из 8, страница 1 из 1
Ошибка при повторном сохранении после отката транзакции
    #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
Ошибка при повторном сохранении после отката транзакции
    #36154721
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
Ошибка при повторном сохранении после отката транзакции
    #36154757
Ptn
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Собственно у вас при первом сохранени объекту назначается ID, объект вы не закрываете, ID не чистите.

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

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

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

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

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

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

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

PS: Или я чего не понял ?
Во время сохранения вызывается метод %ExistsId , который проверяет наличие данных в глобали с таким ID. Зачем генерировать ошибку при проверке, если данных нет? Попробуйте вызвать метод %ExistsId у класса наследника с ID, которого не существует - генерируется ошибка! Просто, как уже говорил, надо бы сначала проверить, что вообще существуют данные с таким ID, а потом уже определять класс. Вот как-то так...
...
Рейтинг: 0 / 0
Ошибка при повторном сохранении после отката транзакции
    #36155951
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
Ошибка при повторном сохранении после отката транзакции
    #36155978
Ptn
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Socratdv
Не вижу смысла чистить ID после сохранения - ведь счетчик ID уже инкрементирован, просто отсутвует запись с таким ID - зачем еще раз инкрементировать счетчик и присваивать объекту новый ID?

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

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

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

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

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

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

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

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


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