Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M Новый топик    Ответить
 Свойство Deleted, %OnDelete  [new]
nurlybekovnt
Member

Откуда:
Сообщений: 17
Приветствую всех, столкнулся с такой проблемой, прошу помощи, кто-то с большими практическими навыками думаю уже реализовывал такое. Стояла задача не удалять никакие объекты из базы, из-за этого добавил Property Deleted As %Boolean [ InitialExpression = 0 ]; в класс. И в переопределил метод %OnDelete:
ClassMethod %OnDelete(oid As %ObjectIdentity) As %Status [ Private, ServerOnly = 1 ]
{
s person = ..%Open(oid)
s person.Deleted = 1
d person.%Save()
Quit $$$ERROR(2112, "DeleteOperationNotAllowed")
}

В документации сказано, если %OnDelete возвращает $$$OK, то объект удалится, а необходимо обратное. Все было прекрасно, но обнаружилось что, Deleted не изменяется. После того как я вызываю do ##class(Person).%DeleteId(29564), объект не удаляется и свойство тоже не изменяется. Сам покапался, думаю это из-за roll back, если в удалении выкидывается ошибка, то каша возвращает в прежнее состояние объект. Теперь к вопросу: возможно ли как-то исправить данное решение, чтобы конечная цель была достигнута или есть ли у кого-то более профессиональное решение данной задачи?
1 ноя 17, 11:44    [20918360]     Ответить | Цитировать Сообщить модератору
 Re: Свойство Deleted, %OnDelete  [new]
DAiMor
Member

Откуда: Volzhsky -> Moscow -> CZ, Brno
Сообщений: 2410
nurlybekovnt,

Я бы посоветов создать отдельную таблицу в которую помещать сериализованное представление объекта для последующего возможного восстановления.
Таким образом, объект будет реально удален, но можно будет сохранить информацию о нем для истории, кто когда и может зачем удалил.

С вашим способом, нужно будет всегда помнить о том что есть удаленные объекты и их например нужно будет скрывать в результатах поиска.
Если вам нужно чтобы такие объекты находились в результатах поиска, но просто с флагом помеченных на удаление. Тогда стоит пойти иначе, просто не использовать стандартное удаление, а просто ставить флаг Deleted.
1 ноя 17, 13:08    [20918711]     Ответить | Цитировать Сообщить модератору
 Re: Свойство Deleted, %OnDelete  [new]
DAiMor
Member

Откуда: Volzhsky -> Moscow -> CZ, Brno
Сообщений: 2410
nurlybekovnt,

Наш человек, создал вопрос и тут и на Developer Community. Я там кстати вопрос раньше заметил (благодаря уведомлениям), ответил, обратил внимание на вопрошающего, и решил проверить здесь.
1 ноя 17, 13:10    [20918721]     Ответить | Цитировать Сообщить модератору
 Re: Свойство Deleted, %OnDelete  [new]
nurlybekovnt
Member

Откуда:
Сообщений: 17
DAiMor,

Да, я там тоже написал, здесь на форуме как-то кто-то рекомендовал писать свои вопросы там, по этой причине там написал.
Цель Deleted исходит из безвыходности, потому что к удаляемому объекту Person могут другие объекты иметь внешний ключ Many-To-One, а каша из-за этого не позволит удалить Person, и это правильно.
И я решил сделать свойство Deleted, да, верно перед каждым запросом мне теперь придется смотреть свойство, и еще в добавок перед %DeleteId нужно менять свойство Deleted на 1. А если есть объекты, ссылающиеся на данный Person, каша сама не позволит удалить его и я со спокойной душой запускаю %DeleteId.
Чтобы на немного облегчить работу я хотел переопределить %OnDelete, и не беспокоится об изменении свойства перед %DeleteId.
1 ноя 17, 14:07    [20918926]     Ответить | Цитировать Сообщить модератору
 Re: Свойство Deleted, %OnDelete  [new]
Ptn
Guest
nurlybekovnt,
В документации сказано, если %OnDelete возвращает $$$OK, то объект удалится, а необходимо обратное. Все было прекрасно, но обнаружилось что, Deleted не изменяется. После того как я вызываю do ##class(Person).%DeleteId(29564), объект не удаляется и свойство тоже не изменяется.


Вот смотрите :
1 - Идет вызов %DeleteId
2 - Открывается транзакция 1
3 - Вызывается %OnDelete
3.1 - В нем вы открываете объект
3.2 - Устанавливаете Deleted = 1
3.3 - Сохраняете объект
3.3.1 - Открывается транзакция 2
3.3.2 - Происходят вызовы %OnBeforeSave %OnAddToSaveSet %OnAfterSave
3.3.3 - Коммитится транзакция 2
3.4 - Вы выходите из %OnDelete с ошибкой $$$ERROR(2112, "DeleteOperationNotAllowed")
4 - Объект видя ошибку откатывает транзакцию 1

Все ... теперь у вас объект опять в том же состоянии что и до вызова %DeleteId
1 ноя 17, 14:13    [20918954]     Ответить | Цитировать Сообщить модератору
 Re: Свойство Deleted, %OnDelete  [new]
Ptn
Guest
nurlybekovnt,

В порядке безобразия и вредных советов можете попробовать следующее

ClassMethod %OnDelete(oid As %ObjectIdentity) As %Status [ Private, ServerOnly = 1 ]
{
 s person = ..%Open(oid)
 s person.Deleted = 1
 d person.%Save()
 try { tcommit  tstart  } catch {}
 Quit $$$ERROR(2112, "DeleteOperationNotAllowed")
}
1 ноя 17, 14:17    [20918968]     Ответить | Цитировать Сообщить модератору
 Re: Свойство Deleted, %OnDelete  [new]
nurlybekovnt
Member

Откуда:
Сообщений: 17
DAiMor,
Спасибо вам за отзывчивость

Ptn,
Спасибо вам, за столь глубочайшее объяснение и приведенное решение
1 ноя 17, 14:31    [20919031]     Ответить | Цитировать Сообщить модератору
 Re: Свойство Deleted, %OnDelete  [new]
Блок А.Н.
Member

Откуда: Новосибирск
Сообщений: 3541
Если система не в зеркале и не шэдоуится, я бы перед Save посоветовал отключить журналирование, а после Save включать. Тогда при откате транзакции система не увидит изменения и не откатит.

Если журналировани отключить нельзя, то я сделал бы отдельную систему. При удалении метод должен записать куда-то в нежурналируемый глобал (например, CACHETEMP) пару class/id, а отдельный процесс должен проверять это место и отмечать удаленными данные по этому глобалу.

А еще правильнее просто использовать не стандартное удаление, а свой метод, типа MarkDeleted, при этом заглушку в %OnDelete оставить. Потому что откат транзакции - очень дорогая процедура, и строит на ней штатные механизмы неправильно.

Способ Ptn (tcommit tstart) хоть и изящный, но я бы побоялся его использовать, из-за возможных неявных эффектов. Например, что-то может происходить до tcommit (в этом или следующей версии Каше), при этом вы эти изменения закоммитите.
1 ноя 17, 18:27    [20919919]     Ответить | Цитировать Сообщить модератору
Все форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M Ответить