Get propertyy value in trigger
Hello,
I work with trigger and I need afeter update make INSERT into LogTable value of prorerty of saved class. This is what i have in this monent.
S cls=##class(%Dictionary.CompiledClass).%OpenId(className)
F i = 1:1:cls.Properties.Count() {
S prop = cls.Properties.GetAt(i)
S propName = prop.Name
S value={propName*N}
}
How Can I get value given "prop".
Thank you
Hi Alexandr,
If property is in the context of this class then you could try
set value=$property($THIS,propName)
If you make the code blocks outer method a generator, e.g. [ CodeMode = objectgenerator ]
then you can bake the property accessor into the underling INT code, e.g.
do %code.WriteLine(" set value=.."_propName)
this approach means you don't have to make any repetitive IO calls to dictionary at run time.
If you need an expanded example then I can bash something out.
Sean.
Dear Sean I would glad to get a code for update trigger that iterate on all updated properties of a derived class and writes log to a log table.
Here is an expanded example...
{
set x=%code
for i=1:1:%compiledclass.Properties.Count() {
#dim p As %CompiledProperty
set p=%compiledclass.Properties.GetAt(i)
set name=p.Name
if $extract(p.Name)'="%" do x.WriteLine(" do ..logProp("""_p.Name_""",.."_p.Name_")")
}
}
Method logProp(propName, propValue)
{
// call your macro logger here, or replace call to logProp with your macro above
}
Let's say you had a property...
When you compile the class, your logProps method would look like this...
do ..logProp("firstName",..firstName) }
There is an article on DC that explains method generators in more depth..
https://community.intersystems.com/post/exploring-code-generation-cach%C3%A9-method-generators
Are you using a trigger generator or writing your own code? Can you send the whole trigger definition for review?
{
S className = ..%ClassName(1)
S cls=##class(%Dictionary.CompiledClass).%OpenId(className)
F i = 1:1:cls.Properties.Count() {
S prop = cls.Properties.GetAt(i)
S propName = prop.Name
i prop.Name'["%" {
b
S idRow = {Id}
x "s value={"_propName_"}"
s date=+$h,time=$p($h,",",2)
&sql(INSERT INTO LogClass (className, dateOfChange, fieldName, ip, newValue, oldValue, operation, timeOfChange, users)
VALUES (:classname,:date,:propName, '192:168:1:1',:value,'','Insert',:time,'asfasf'))
}
}
You can combine triggers and method generators into trigger generators like this:
Class User.Class1 Extends %Persistent { Property prop1 As %String; Property prop2 As %String; Trigger NewTrigger [ CodeMode = objectgenerator, Event = INSERT, Time = AFTER ] { #dim class As %Dictionary.CompiledClass = %compiledclass set proplist = "" for i=1:1:class.Properties.Count() { #dim prop As %Dictionary.CompiledProperty = class.Properties.GetAt(i) if prop.Internal || prop.Calculated || prop.ReadOnly || prop.Private || prop.Identity || prop.MultiDimensional continue set proplist = proplist _ $lb(prop.Name) } do %code.WriteLine($$$TAB _ "set ^dbg($i(^dbg)) = $lb({" _$lts(proplist, "},{") _ "})") quit $$$OK } /// do ##class(User.Class1).Test() ClassMethod Test() { do ..%KillExtent() kill ^dbg &sql(INSERT INTO Class1 (prop1, prop2) Values ('Alice', 1)) &sql(INSERT INTO Class1 (prop1, prop2) Values ('Bob' , 2)) zw ^dbg }
Test:
Here's whats going on during compilation.
And at runtime only set ^dbg gets hit
That said I'd have automatically generated some log class and called method log there, passing all properties.
Some docs:
Thank you all, dear friends for your help. You all really helped me.
Take a look at this article:
https://community.intersystems.com/post/tracking-data-changes-audit-log