powered by simpleCommunicator - 2.0.59     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M [игнор отключен] [закрыт для гостей] / Хранение истории изменений объектов
57 сообщений из 57, показаны все 3 страниц
Хранение истории изменений объектов
    #37458232
Vixler
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте.

Хотелось бы узнать способы хранения истории изменений. Поделитесь, плиз, кто как хранит историю изменений объектов, как это реализовано. В поиске на форуме находил пару тем, но они древние и не отвечают на все вопросы.

Задача такова: при изменении какого-то свойства объекта надо сохранять в базе запись об этом изменении с новым значением, именем юзера, под которым изменилось это свойство, ну и с датой и временем изменения, естественно. Отсюда возникают вопросы: как отследить, когда изменилось конкретное свойство? В чём хранить эти изменения? (в смысле, пользоваться классами или напрямую лучше писать в глобалы)

Сейчас на событии OnAfterSave пробегаюсь по свойствам, ищу в базе последнее изменение свойства, сравниваю их и если они не равны, записываю новую запись. Причём такой поиск с использованием классов (ClassHistoryObject) оказался довольно долгим, поэтому думаю писать прямо в глобалы. Проблема ещё и в том, что если свойство представляет ссылку на объект, то его тоже надо как-то разобрать, чтобы хранить не просто айдишник (который со временем может быть удалён и не поймёшь потом, а что было в этом объекте), а описание его полей. Но с этим я как-то ещё разобрался, у всех персистент и сериал обжект классов должен быть обязательным метод ToString(), который возвращает описание объекта. А вот как быть со списками и отношениями...

В общем, если кто с этим сталкивался, подскажите, если не трудно, как это лучше организовать.
Спасибо.
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37458322
Фотография krvsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vixlerесли кто с этим сталкивался, подскажите, если не трудно, как это лучше организовать
Применяем свою "обёртку" для изменения данных в БД...
Т.е. ничего из стандартного не трогаем, оставляя возможность его использования но при этом никакие изменения не запишутся никуда... Делаем свои процедурки/функции/методы, коими все должны пользоваться при стандартной модификации БД. Вот эти-то процедурки/функции/методы и ведут "учёт" всех изменений.

Всё новое предпочитаем хранить в классах, дабы была возможность работы sql и zen...
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37458442
Фотография DAiMor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
в одном из проектов в котором я участвовал, хранение истории было построено довольно просто в ущерб занимаемому месту в бд
при изменении объекта будь то через объект или через SQL, в специальном глобале, это был так же как имена глобалов для хранения данных объекта, только на конце "H" и в него хранилось в разрезе каждого ID, времени изменения копия $LB() с данными и именем пользователя под которым произошло изменение, в дальнейшем когда требовалось просмотреть историю изменения то или иного объекта, через интерфейс системы, выводилась таблица с наиболее интересующими полями, где каждая строчка отдельное изменение. и можно всю проследить историю изменения сразу. вроде использовалось %OnAfterSave и триггеры для отлова изменений через SQL.

в другом проекте, используется журнал, куда регистрируются события разного вида в том числе и изменения документа, и на каждое поле своя запись в журнале, и когда пользователь хочет просмотреть историю, он видит всю историю по этому объекту хронологически, и для каждого изменения отображается какое значение было до изменения и какое стало после. для всех событий и всех объектов используется один журнал. с таким журналом, администратор может просматривать изменения по одному документу или например, что изменял пользователь в указанный период, так же и попытки авторизации и прочее. только %OnAfterSave, через SQL изменений не происходит.
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37459572
doublefint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vixler, если позволяет логика приложения, можно выгружать перед изменением версию на диск

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
/// Выгрузка при изменении
Class test.version Extends (%Persistent, %Populate, %XML.Adaptor) {

/// VERSIONPROPERTY = <property> means that the <property> in memory will be compared to
/// the <property> on disk during an update. If different a concurrency conflict
/// error will be reported and the save will fail.
Parameter VERSIONPROPERTY As STRING = "Version";
/// Свойство - Версия объекта - на него указывает системе параметр класса <parameter>VERSIONPROPERTY</parameter>
Property Version As %Integer [ InitialExpression =  1 ,Private ]; 


/// Директория для истории изменений 
Parameter DIR As %String = "c:\temp\";

/// Свойство
Property Name As %String;

/// This callback method is invoked by the <METHOD>%Save</METHOD> method to 
/// provide notification that the object is being saved. It is called before 
/// any data is written to disk.
/// 
/// <P><VAR>insert</VAR> will be set to  1  if this object is being saved for the first time.
/// 
/// <P>If this method returns an error then the call to <METHOD>%Save</METHOD> will fail.
Method %OnBeforeSave(insert As %Boolean) As %Status [ Private, ServerOnly =  1  ] {
 if ('insert) && (..%Id()'="") && (..%IsModified()) {
  JOB ..OnChangeExport(..%Id())
 }
 Quit $$$OK
}

/// Выгрузка перед сохранением
ClassMethod OnChangeExport(id As %String) As %Status [CodeMode = generator ] {
 s %code($i(%code))="  s stored=..%OpenId(id) Q:'$IsObject(stored) $$$OK "
 s %code($i(%code))="  s file="""_%parameter("DIR")_%class_".""_stored.%Id()_"".""_stored.Version_"".""_$USERNAME_"".xml"" "
 s %code($i(%code))="  o file:""WNU"" u file d stored.XMLExport() k stored c file "
 s %code($i(%code))="  Q $$$OK "
 Q $$$OK
}

}
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37460143
Vixler
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
DAiMorв другом проекте, используется журнал, куда регистрируются события разного вида в том числе и изменения документа, и на каждое поле своя запись в журнале, и когда пользователь хочет просмотреть историю, он видит всю историю по этому объекту хронологически, и для каждого изменения отображается какое значение было до изменения и какое стало после. для всех событий и всех объектов используется один журнал. с таким журналом, администратор может просматривать изменения по одному документу или например, что изменял пользователь в указанный период, так же и попытки авторизации и прочее. только %OnAfterSave, через SQL изменений не происходит.

Вот так же хочу сделать. А как у вас выглядела вообще структура классов или глобалов для хранения истории? Сейчас стоит проблема сравнения текущего значения поля с предыдущим ранее сохранённым значением. Если пробегаться по журналу в поисках последней версии, то чем больше было изменений, тем дольше будет поиск. Как у вас это решалось? И как происходило хранение изменений полей-ссылок, отношений и списков? Ну к примеру. В классе есть поле-отношение один-ко-многим Users, описывающее список юзеров, причём каждый объект списка-отношения - это объект класса User. В какой-то момент список пополняется новым юзером. Как в таком случае у вас бы хранилась информация об этом изменении?

Кстати, почему может не работать <propertyName>GetStored? Пишет ошибку:

>w a.IsBlockedGetStored()

Quit $Select(id'="":$listget($g(^User(id)),18),1:"") }
^
<UNDEFINED>zIsBlockedGetStored+1^User.1 *id


doublefintVixler, если позволяет логика приложения, можно выгружать перед изменением версию на диск +

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
/// Выгрузка при изменении
Class test.version Extends (%Persistent, %Populate, %XML.Adaptor) {

/// VERSIONPROPERTY = <property> means that the <property> in memory will be compared to
/// the <property> on disk during an update. If different a concurrency conflict
/// error will be reported and the save will fail.
Parameter VERSIONPROPERTY As STRING = "Version";
/// Свойство - Версия объекта - на него указывает системе параметр класса <parameter>VERSIONPROPERTY</parameter>
Property Version As %Integer [ InitialExpression =  1 ,Private ]; 


/// Директория для истории изменений 
Parameter DIR As %String = "c:\temp\";

/// Свойство
Property Name As %String;

/// This callback method is invoked by the <METHOD>%Save</METHOD> method to 
/// provide notification that the object is being saved. It is called before 
/// any data is written to disk.
/// 
/// <P><VAR>insert</VAR> will be set to  1  if this object is being saved for the first time.
/// 
/// <P>If this method returns an error then the call to <METHOD>%Save</METHOD> will fail.
Method %OnBeforeSave(insert As %Boolean) As %Status [ Private, ServerOnly =  1  ] {
 if ('insert) && (..%Id()'="") && (..%IsModified()) {
  JOB ..OnChangeExport(..%Id())
 }
 Quit $$$OK
}

/// Выгрузка перед сохранением
ClassMethod OnChangeExport(id As %String) As %Status [CodeMode = generator ] {
 s %code($i(%code))="  s stored=..%OpenId(id) Q:'$IsObject(stored) $$$OK "
 s %code($i(%code))="  s file="""_%parameter("DIR")_%class_".""_stored.%Id()_"".""_stored.Version_"".""_$USERNAME_"".xml"" "
 s %code($i(%code))="  o file:""WNU"" u file d stored.XMLExport() k stored c file "
 s %code($i(%code))="  Q $$$OK "
 Q $$$OK
}

}


Попробовал сделать экспорт объекта в XML-файл функцией XMLExport, когда дошло до поля-отношения, вывалилась ошибка. Не хочет что-то функа эта работать с отношениями.
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37460150
Фотография kolesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vixler,

Мы сделали класс, от которого унаследованы все хранимые объекты системы, в нем перегрузили %OnBeforeSave, %OnDelete и %OnAfterSave.
В зависимости от типа изменения (создание, изменение, удаление), пишем содержание изменения в историю.
Потом можно просмотреть требуемую информацию и выполнить откаты в случае необходимости (простые откаты, разумеется).
Вот так примерно:
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37460165
Vixler
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
2kolesov:

Пара вопросов, если можно:

1. Открыли объект через %OpenId, изменили одно/несколько полей, делаем %Save(). Теперь нужно сделать запись в журнал, для этого надо узнать, какие поля были изменены. Каким образом вы это делаете? Через метод <propertyName>GetStored() или через sql-запрос?

2. В приложенном вами скрине, насколько я понял, два поля простых типов %String и %TimeStamp. А как вы обрабатываете поля-ссылки, поля-отношения и поля-списки?

Спасибо.
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37460219
Фотография kolesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vixler2kolesov:

Пара вопросов, если можно:

1. Открыли объект через %OpenId, изменили одно/несколько полей, делаем %Save(). Теперь нужно сделать запись в журнал, для этого надо узнать, какие поля были изменены. Каким образом вы это делаете? Через метод <propertyName>GetStored() или через sql-запрос?

2. В приложенном вами скрине, насколько я понял, два поля простых типов %String и %TimeStamp. А как вы обрабатываете поля-ссылки, поля-отношения и поля-списки?

Спасибо.
1. Через метод <propertyName>GetStored()

2. В примере первое поле - ссылка на объект. В том же суперклассе (где пишется история) есть метод, представляющий этот объект в текстовом виде. В данном случае описание нефтепродукта - это результат работы такого метода, а квадратных скобочках в конце - его айди в БД. По-умолчанию этот метод возвращает "[ID]" а для некоторых наиболее полезных объектов он перегружен, как на картинке - другой пример: "т/х Нарьянмар, рейс 2120, ETA 12-12-11 [1232]", "а там - объект" ;)
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37460232
Vixler
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ага, спасибо за ответы.

А что насчёт списков и отношений один-ко-многим? Как у вас тогда происходит запись? Допустим поле представляет список из 350 ссылок на объекты какого-либо класса. В определённый момент одна ссылка удаляется(/добавляется/изменяется). Какая запись тогда вносится в журнал? Перечисление всех этих объектов в текстовом виде? Просто такая строка будет огромной и анализировать её наверное будет сложновато. Я тут думаю может писать что-то вроде "field = listOfSomeObjects, operation = 'добавление элемента в список', value = obj.ToString()"
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37460240
Фотография kolesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
VixlerАга, спасибо за ответы.

А что насчёт списков и отношений один-ко-многим? Как у вас тогда происходит запись? Допустим поле представляет список из 350 ссылок на объекты какого-либо класса. В определённый момент одна ссылка удаляется(/добавляется/изменяется). Какая запись тогда вносится в журнал? Перечисление всех этих объектов в текстовом виде? Просто такая строка будет огромной и анализировать её наверное будет сложновато. Я тут думаю может писать что-то вроде "field = listOfSomeObjects, operation = 'добавление элемента в список', value = obj.ToString()"

- Изменения отношений записывается со стороны "много"

- Поля-списки, отношения "родитель-потомок" и прочие нестабильные артефакты не используем - система должна быть как риск-процессор (минимум сущностей при максимуме эффективности) и облегчение работы с историей - тому лишнее подтверждение ;)
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37460288
doublefint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
VixlerПопробовал сделать экспорт объекта в XML-файл функцией XMLExport, когда дошло до поля-отношения, вывалилась ошибка. Не хочет что-то функа эта работать с отношениями.
Что за ошибка? Не настроен экспорт связанных объектов в XML?
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37460305
Vixler
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А списки строк? :)

Ну так вроде всё понятно, спасибо, начинает что-то вырисовываться. Списки ссылок мы тоже решили не юзать, но так, на всякий случай, думал обрабатывать и эту ситуацию. К тому же есть ещё %SerialObject-классы, у которых нет функции %Save(), и не получится со стороны таких объектов (в отношениях "один-ко-многим") записать изменение в журнал. Или вы и их не юзаете? )
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37460370
Фотография kolesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
VixlerА списки строк? :)

Ну так вроде всё понятно, спасибо, начинает что-то вырисовываться. Списки ссылок мы тоже решили не юзать, но так, на всякий случай, думал обрабатывать и эту ситуацию. К тому же есть ещё %SerialObject-классы, у которых нет функции %Save(), и не получится со стороны таких объектов (в отношениях "один-ко-многим") записать изменение в журнал. Или вы и их не юзаете? )
Списки строк конечно используем. Как и всяческие другие коллекции. Но не как свойства хранимых классов. То есть вообще ни одного хранимого свойства типа *List* или *Array* в системе за последних 4 года не появилось. А если бы появилось - программист бы огрёб ;)

А "на всякий случай" мы в подобной ситуации просто не запишем изменение - вреда от этого чуть (ну не узнаем мы кто в списке подменил элемент и как). Если решение эффективно на 99,9 процентов, то на оставшуюся десятую долю можно забить - в конце концов есть видео, пыточная комната, полиграф и прочие вполне эффективные и недорогие айти-инструменты - незачем лишать себя разнообразия и удовольствий ;)
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37460412
Фотография DAiMor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
VixlerВот так же хочу сделать. А как у вас выглядела вообще структура классов или глобалов для хранения истории? Сейчас стоит проблема сравнения текущего значения поля с предыдущим ранее сохранённым значением. Если пробегаться по журналу в поисках последней версии, то чем больше было изменений, тем дольше будет поиск. Как у вас это решалось? И как происходило хранение изменений полей-ссылок, отношений и списков? Ну к примеру. В классе есть поле-отношение один-ко-многим Users, описывающее список юзеров, причём каждый объект списка-отношения - это объект класса User. В какой-то момент список пополняется новым юзером. Как в таком случае у вас бы хранилась информация об этом изменении?

дело в том что у нас поля несколько иного вида, они хранятся в глобале объекта, имеют не стандартный тип а наш, и поэтому мы у себя контролируем что из полей изменилось а что нет, и добавляем соответствующее событие в журнал.
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37515480
Vixler
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Опять вернулся к этой многострадальной истории...

Никак не могу разобраться как сравнивать два значения, новое и сохранённое. Если это простой тип (строка, число) - это ладно. Пофик, если это ссылка на другой объект, сравниваем айдишники. Но если это список (простых типов) или ссылка на объект типа %SerialObject?

Например,

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
s a.SomePeriod.DateBegin = "2011-01-01"
s a.SomePeriod.DateEnd = "2040-01-01"
w a.%Save()
 1 
w a.SomePeriodGetStored(a.%Id())
 2011 - 01 - 01   00 : 00 : 00  2040 - 01 - 01   00 : 00 : 00 
w a.SomePeriod
 3 @VSCCMS.Blank.DatePeriod

SomePeriodGetStored возвращает одно представление объекта, а SomePeriod - другое. Как их привести к одинаковому виду?

В документации пишут что-то про StorageToLogical, но её нету у этого класса, как и у всех других...

То же самое со списком простых классов. Никак не могу привести два значения к одному виду. Можно конечно использовать вычисляемые поля, которые будут описывать списки и объекты SerialObject, но это надо будет в каждом классе самому отслеживать такие поля.
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37519337
Vixler
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
И всё-таки. Как преобразовать значение к хранимому виду? Вот здесь про функцию LogicalToStorage() сказано, что оно опционально. Но не написано, где эта опция включается, чтобы эта функция была доступна. Может кто-нибудь знает?
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37519383
ser_shu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
VixlerИ всё-таки. Как преобразовать значение к хранимому виду? Вот здесь про функцию LogicalToStorage() сказано, что оно опционально. Но не написано, где эта опция включается, чтобы эта функция была доступна. Может кто-нибудь знает?
Опционально - можете добавить методы с этими именами в описание класса и они будут исполняться.
Обычно все хранят значения Logical, поэтому никто эти методы не использует.
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37519385
Vixler
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ладно, но как тогда корректно сравнить ранее сохранённое значение, полученное по GetStored и текущее значение, когда %Save() ещё не выполнен? Для случая со списком или ссылкой на %SerialObject?
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37671878
Фотография krvsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Подниму темку...

Решил хранить историю модификации классов таким образом:
- создал абстрактный класс

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
/// Расширение для класса с данными
Class mvr.sys.cls.data [ Abstract ]
{

/// Дата модификации
Property changeDate As %Date(FORMAT = 3)[ 
	SqlComputeCode = { 
		Set {changeDate}=+$h 
	}, SqlComputed 
];

/// Время модификации
Property changeTime As %Time[ 
	SqlComputeCode = { 
		Set {changeTime}=$p($h,",",2)
	}, SqlComputed 
];

/// Сотрудник выполневший модификацию данных
Property changeEmployee As %String[ 
	SqlComputeCode = { 
		Set {changeEmployee}= ##class({%%CLASSNAME}).saveEmployee() 
	}, SqlComputed 
];

/// Записать пользователя
ClassMethod saveEmployee() As %String
{
	s val=$g(%session.Data("userId"))
	q ""
	s val=##class(mvr.data.employee).%OpenId(val).name
	q val
}

}



- Применяю наследование

Код: vbnet
1.
2.
/// Пользователи
Class mvr.data.employee Extends (%Persistent, mvr.sys.cls.data)



Когда делаю insetr через SQL - данные записываются.
Но при update или манипуляций классом ничего не меняется и не записывается...

Как бы победить еще и это?
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37671887
Фотография DirksDR
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
krvsa,

s val=$g(%session.Data("userId"))
q ""
;а будут ли выполняться нижние строки, вроде выход уже был?
s val=##class(mvr.data.employee).%OpenId(val).name
q val
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37671890
Фотография krvsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DirksDR , это тестовый вариант... Суть вопроса не в этом.
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37671894
Фотография krvsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пусть будет например так:

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
/// Расширение для класса с данными
Class mvr.sys.cls.data [ Abstract ]
{

/// Дата модификации
Property changeDate As %Date(FORMAT = 3)[ 
	SqlComputeCode = { 
		Set {changeDate}=+$h 
	}, SqlComputed 
];

/// Время модификации
Property changeTime As %Time[ 
	SqlComputeCode = { 
		Set {changeTime}=$p($h,",",2)
	}, SqlComputed 
];

/// Сотрудник выполневший модификацию данных
Property changeEmployee As %String[ 
	SqlComputeCode = { 
		Set {changeEmployee}= ##class({%%CLASSNAME}).saveEmployee() 
	}, SqlComputed 
];

/// Записать пользователя
ClassMethod saveEmployee() As %String
{
	s val=$g(%session.Data("userId"))
	q:val="" ""
	s val=##class(mvr.data.employee).%OpenId(val).name
	q val
}

}
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37671903
Фотография krvsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Всё это срабатывает только при добавлении данных insert... Более ничего данных не меняет.

Меня даже устроит если будут изменения по update.
Т.к. при классовом подходе я просто создам медод, альтернативный %Save() и проблему т.о. решу...
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37671928
Фотография krvsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Прошу прощения Добавление работает и классовым методом, данные записываются

Код: vbnet
1.
2.
3.
MVR>s o=##class(mvr.data.employee).%New() zw o s o.name="test" s ok=o.%Save() zw ok k o
o=<OBJECT REFERENCE>[1@mvr.data.employee]
ok=1



Пришлось усложнить метод

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
/// Расширение для класса с данными
Class mvr.sys.cls.data [ Abstract ]
{

/// Дата модификации
Property changeDate As %Date(FORMAT = 3)[ 
	SqlComputeCode = { 
		Set {changeDate}=+$h 
	}, SqlComputed 
];

/// Время модификации
Property changeTime As %Time[ 
	SqlComputeCode = { 
		Set {changeTime}=$p($h,",",2)
	}, SqlComputed 
];

/// Сотрудник выполневший модификацию данных
Property changeEmployee As %String[ 
	SqlComputeCode = { 
		Set {changeEmployee}= ##class({%%CLASSNAME}).saveEmployee() 
	}, SqlComputed 
];

/// Записать пользователя
ClassMethod saveEmployee() As %String
{
	q:'$d(%session) ""
	s val=$g(%session.Data("userId"))
	q:val="" ""
	s val=##class(mvr.data.employee).%OpenId(val).name
	q val
}

}



Осталось разобраться с модификацией экземпляра. Дабы всё обновлялось и тогда...
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37671945
andrew_tsw
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Update a timestamp property on UPDATE and INSERT via SqlComputeOnChange
Отличие в SqlComputeOnChange = (%%INSERT, %%UPDATE)
При работе через объекты тоже должно обновляться.
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37671964
YuraM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день, krvsa!
Может быть не совсем то, что Вам надо, но мы у себя ведем лог изменений примерно таким способом...

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
Class DATA.CORE.Kernel Extends (%Populate, %XML.Adaptor, %ZEN.DataModel.Adaptor) [ Abstract, Inheritance = right ]
{

/// системная дата записи
Property recordDate As %Date(ZENHIDDEN = 1, ZENLABEL = "Дата зипису") [ InitialExpression = {+$H} ];

/// системная дата редактирования
Property openLog [ MultiDimensional, Private ];

/// пользователь сделавший запись
Property userID As DATA.SYSTEM.USERS(ZENHIDDEN = 1, ZENLABEL = "Користувач виконавший запис");

Method %OnOpen() As %Status [ Private, ServerOnly = 1 ]
{
 s classname = ..%ClassName(1)

 s cdef = ##class(%Dictionary.ClassDefinition).%OpenId(classname)
 s pp = $zobjclassmethod(classname, "%Open" , ..%Oid())

 // get list of properties
 s count = cdef.Properties.Count()
 For i = 1:1:count {
   s ..openLog(..%Oid(),cdef.Properties.GetAt(i).Name)= $zobjproperty(pp, cdef.Properties.GetAt(i).Name)
 }

  Quit $$$OK
}

Method %OnAfterSave(insert As %Boolean) As %Status
{
 q:insert=1 $$$OK

 s classname = ..%ClassName(1)
 s ts = $zts

 s cdef = ##class(%Dictionary.ClassDefinition).%OpenId(classname)
 s pp = $zobjclassmethod(classname, "%Open" , ..%Oid())

 // get list of properties
 s count = cdef.Properties.Count()
 For i = 1:1:count {
   s oldval = $g(..OpenLog(..%Oid(),cdef.Properties.GetAt(i).Name))
   s newval = $zobjproperty(pp, cdef.Properties.GetAt(i).Name)

   if oldval'=newval
   {
     s ^SaveLog(ts, ..%Oid(), cdef.Properties.GetAt(i).Name, "old") =  oldval 
     s ^SaveLog(ts, ..%Oid(), cdef.Properties.GetAt(i).Name, "new") =  newval 
   }

 }

 Quit $$$OK
}


}
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37672371
Фотография krvsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuraM , про эти методы я в курсе...
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37672382
Фотография krvsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrew_tsw Update a timestamp property on UPDATE and INSERT via SqlComputeOnChange
Не совсем понял как этим пользоваться...

andrew_tswОтличие в SqlComputeOnChange = (%%INSERT, %%UPDATE)
Т.е. мне это нужно добавить в определение свойств?

andrew_tswПри работе через объекты тоже должно обновляться.
А есть ть ли вариант, что бы через объекты эти свойства не менялись? Просто есть желание оставить и т.с. стандартный способ изменения данных...
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37672409
Фотография krvsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrew_tsw , я таки понял что нужно написать. Спасибо, всё работает

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
/// Расширение для класса с данными
Class mvr.sys.cls.data [ Abstract ]
{

/// Дата модификации
Property changeDate As %Date(FORMAT = 3) [ SqlComputeCode = { 
		Set {changeDate}=+$h 
	}, 
	SqlComputed, 
	SqlComputeOnChange = (%%INSERT, %%UPDATE)
];

/// Время модификации
Property changeTime As %Time [ SqlComputeCode = { 
		Set {changeTime}=$p($h,",",2)
	}, 
	SqlComputed, 
	SqlComputeOnChange = (%%INSERT, %%UPDATE)
];

/// Сотрудник выполневший модификацию данных
Property changeEmployee As %String [ SqlComputeCode = { 
		Set {changeEmployee}= ##class({%%CLASSNAME}).saveEmployee() 
	}, 
	SqlComputed, 
	SqlComputeOnChange = (%%INSERT, %%UPDATE)
];

/// Записать пользователя
ClassMethod saveEmployee() As %String
{
	q:'$d(%session) ""
	s val=$g(%session.Data("userId"))
	q:val="" ""
	s val=##class(mvr.data.employee).%OpenId(val).name
	q val
}

}
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37672415
Фотография krvsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Осталась лишь такая модификация
Есть ть ли вариант, что бы через объекты эти свойства не менялись?
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37672652
doublefint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
krvsa, ReadOnly ?
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37672756
Фотография krvsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
doublefintReadOnly ?
Не совсем понял про что это?

Немного опишу свою задумку...
Есть некие данные с тем абстрактным классом докучи... Предполагается сделать некий экспорт/импорт тех данных. Поэтому не хочется чтобы в те свойства занеслись текущие значения. А хочется просто переписать что ранее экспортировали.

Пока рассматириваю вариант с неким значением
Код: vbnet
1.
%session.Data("logNoSave")=1



Но может есть и другой вариант...
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37672853
doublefint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
krvsa Есть ть ли вариант, что бы через объекты эти свойства не менялись?
Код: vbnet
1.
Property propName As %String [ ReadOnly ];
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37672872
Фотография krvsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
doublefint , при таком варианте они вообще меняться не будут.
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37673114
doublefint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
krvsa, ну вообще-то, оно таки расчетное, значит так и должно быть. Но посмеемся вместе:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
///Отдельный метод для изменения ридонли свойства 
Method ChangePropNameSet (Arg as %String ) as %Status {
  s i%propName=Arg  
  Q $$$OK
 }

/// И даже класс-метод, раз пошла такая пляска
ClassMethod UpdatePropName(id as %String,val as %String) as %Status {
  &sql(Update %NOCHECK package.classname Set propName=:val Where ID=:id)
  Q:SQLCODE=0 $$$OK
  Q $$$ERROR($$$GeneralError,$system.SQL.SQLCODE(SQLCODE))
}



ISC предоставляет программисту Cache три интерфейса доступа к данным (объектный, sql, прямой). Сколько интерфейсов программист Cache предоставит пользователю?
"Каша снаружи, каша внутри".
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37673281
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
krvsaЕсть ть ли вариант, что бы через объекты эти свойства не менялись?Использовать триггеры не пробовали?
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37673286
Фотография krvsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
doublefint , какой-то подземный ход на чердак... Я не сторонник такого подхода.
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37674680
Ivan.Kokov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
YuraM,
cdef.Properties возвращает только верхушку айсберга, т.е. свойства, унаследованные от предков, остаются скрытыми.
Между тем, и они вполне могут быть изменены, хотя бы и неявно.
Они могут быть, как было сказано, встраиваемыми
Как вы с этим боретесь? Вызываете рекурсивно?

Почему не используете ConstructClone? Если унаследовать базовый класс от %RegisteredObject, то можно перед открытием делать копию, а затем сравнивать с ней

doublefint, совершенно согласен с krvsa, что "через подвал на чердак ходить" как то неправильно
Согласен считать i%... фичей, но это... (это я про "UpdatePropName") - как-то уж очень смело :)
В каких случаях вы этим пользуетесь? Наверняка очень осторожно и в самых крайних случаях? :)
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37674758
doublefint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ivan.Kokov, меня похоже не поняли... Совсем... Как бы донести...
Вот есть возможности (функции с документацией и т.д.), можно сделать и так и эдак.
Почему-то сразу откуда-то возникают стериотипы, что вот такое использование "правильное", а вот такое - противоречит каким-то "религиозным" убеждениям. ISC предоставляет программисту аж три слоя функций. Казалось бы, читай, выбирай, используй, комбинируй, тестируй на соответствие требованиям... Но - нет!!!
Ivan.KokovСогласен считать i%... фичей, но это... (это я про "UpdatePropName") - как-то уж очень смело :)

Смело читать документацию и использовать документированные возможности?
Где эта секретная библия "правильного" разработчика которой вы с krvsa пользуетесь?

Свойство, которое не будет обновляться через объектный интерфес - нате ReadOnly, а чтоб все равно обновлять - нате два способа. Это извращение!!! Так я еще и через Ctrl+Shift+V частенько сгенерированные программы просматриваю, представляете? Оказывается, классы и sql в программы на М компилируются! Ужас! И если мне надо будет, еще и в глобаль залезу, O_o

Чет вы меня совсем запугали, страшно Студию открывать, вдруг там код слишком борзый :)
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37674795
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Использование синтаксиса i%Property хорошо документировано:
i%<PropertyName> Syntax

http://docs.intersystems.com/cache20111/csp/docbook/DocBook.UI.Page.cls?KEY=ROBJ_property_readonly][ReadOnly] and i%PropertyName
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37674820
Ivan.Kokov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
doublefint,

Ivan.KokovСогласен считать i%... фичей, но это... (это я про "UpdatePropName") - как-то уж очень смело :)

doublefintГде эта секретная библия "правильного" разработчика которой вы с krvsa пользуетесь?


Не, мы отдельно и независимо :)
Даже не пытаюсь уравнять себя со старожилами этого форума

Вот вы пишете:
doublefintСвойство, которое не будет обновляться через объектный интерфес - нате ReadOnly, а чтоб все равно обновлять - нате два способа. Это извращение!!! Так я еще и через Ctrl+Shift+V частенько сгенерированные программы просматриваю, представляете? Оказывается, классы и sql в программы на М компилируются! Ужас! И если мне надо будет, еще и в глобаль залезу, O_o

Вы не поверите: и я грешен, бывает, залезаю смотреть инты, да еще и по глобалям шарюсь, и сеты делаю
По рукам себя бью, плачу, а делаю - уж очень хочется побыстрее...
Особенно если есть доступ в рабочую БД :)

Все наоборот!!!
Уверен что я не в курсе про что-то, вот и хочу поучиться. В частности пропнэйм - для чего его может понадобиться менять на лету? Неужто юзерам отдаете право проектировать структуры? Тады, конечно "ой"
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37674843
doublefint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ivan.Kokov, ну слава богам, разобрались! За тон, прошу прощения :(. Насчет propName, смотрите внимательней (выше), это я для примера поле так назвал (неудачно, согласен).
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
///Более типовой пример: 
Class User.Test Extends %Persistent {
 
Property Name as %String[ReadOnly];

ClassMethod UpdateName(id,value)[SqlProc]{
 &sql(Update %NOCHECK SQLUser.Test Set Name=:value Where ID=:id)
}
}
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37674856
doublefint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Виталий, с 2003 интересует как такой вызов (s i%PropName ) будет на Cache Basic? Все никак руки не доходят, ткните носом, плиз :)
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37674906
Ivan.Kokov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
doublefintIvan.Kokov, ну слава богам, разобрались! За тон, прошу прощения :(. Насчет propName, смотрите внимательней (выше), это я для примера поле так назвал (неудачно, согласен).
[/src]
Не, doublefint,
Это я читать разучился
Смешалось все в кучу - обращения в классдеф - проперти, задание значений ридонли...
В следующий раз буду внимательней :)
Это вы извините,
мне самому смешно от себя
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37675648
Фотография krvsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
doublefintГде эта секретная библия "правильного" разработчика которой вы с krvsa пользуетесь?
Я называю это здравым смыслом...
Зачем мне объявлять свойство "только для чтения" если я его активно собираюсь менять? А потом начинаю преодолевать трудности по его заполнению...
Это правильно?
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37675710
doublefint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
krvsaЯ называю это здравым смыслом... Ну так не останавливайте себя в его использовании!
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37676149
Фотография krvsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
doublefint , так я вроде и не останавливаюсь...
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37676462
doublefint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
krvsa, переписка выше об этом не свидетельствует... :(
Попробуйте еще раз.
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37683765
Ymka2007
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
kolesovПотом можно просмотреть требуемую информацию и выполнить откаты в случае необходимости (простые откаты, разумеется).
Вот так примерно:

доброго времни суток
судя по вашей картинке вы как то доработали компонент tablePane
можете поделиться реализацией компонента с возможностью выгрузки в word, excel

спасибо
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37683858
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
doublefintВиталий, с 2003 интересует как такой вызов (s i%PropName ) будет на Cache Basic? Все никак руки не доходят, ткните носом, плиз :)Аналога синтаксису i%<PropertyName> для Caché Basic нет (Prodlog 97628).
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37683922
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ymka2007kolesovПотом можно просмотреть требуемую информацию и выполнить откаты в случае необходимости (простые откаты, разумеется).
Вот так примерно:

доброго времни суток
судя по вашей картинке вы как то доработали компонент tablePane
можете поделиться реализацией компонента с возможностью выгрузки в word, excel

спасибоПосмотрите ещё здесь .
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37683926
doublefint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
servit, восхищаюсь вашим умением находить это всё...
Применение Cache Basic по-прежнему откладывается.
Виталий спасибо!
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37683984
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
doublefintПрименение Cache Basic по-прежнему откладывается.VadimF...Мыш Летучий2) Используете ли Вы кашебейсик и насколько интенсивно?
Или лучше с ним даже не заморачиваться?
Basic у нас используется очень мало.
В мире тоже.
...
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37688758
Фотография kolesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ymka2007kolesovПотом можно просмотреть требуемую информацию и выполнить откаты в случае необходимости (простые откаты, разумеется).
Вот так примерно:

доброго времни суток
судя по вашей картинке вы как то доработали компонент tablePane
можете поделиться реализацией компонента с возможностью выгрузки в word, excel

спасибо
Эту фичу Аленочка делала - попробую уговорить рассказать ;)
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37698301
Фотография Аленочка
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ymka2007
я вышлю вам на почту (на ту что указана в профиле).
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37698685
Ymka2007
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Аленочка,

большое спасибо )), изучаю
пока непоняно вот это zen_flex.TableColumn, это какой то специальный класс?
и вот это "Show the properties of the table"
...
Рейтинг: 0 / 0
Хранение истории изменений объектов
    #37701845
Фотография Аленочка
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ymka2007,

Это наша специальная примочка, чтобы пользователь с интерфейса мог управлять настройками таблиц, менять ширину столбцов, просматривать текст запроса, скрывать столбцы и т.д. zen_flex.TableColumn – это хранимый класс, который содержит настройки столбцов таблицы.
...
Рейтинг: 0 / 0
57 сообщений из 57, показаны все 3 страниц
Форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M [игнор отключен] [закрыт для гостей] / Хранение истории изменений объектов
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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