You are correct. EventData is the field to use. Here's an example  query (run from %SYS namespace):

SELECT UTCTimeStamp, EventSource, EventType, Event, EventData, Username, Description
FROM %SYS.Audit
WHERE (UTCTimeStamp BETWEEN '2018-10-27 00:00:00' and '2018-10-27 23:59:59') AND (EventData = '12345') AND (Namespace = 'ABC')
ORDER BY UTCTimeStamp DESC, SystemID DESC, AuditIndex DESC

You probably want to add a WHERE clause on the Namespace column. The docs for the %SYS.Audit class (https://docs.intersystems.com/irislatest/csp/documatic/%25CSP.Documatic....) suggest using a WHERE clause on UTCTimeStamp to speed up the search.

I think you are asking: "If I have an object open in one process, and another process updates that object or its corresponding row, what's the best way for the first process to make sure that it has the latest version of the data?"

I recommend using %Reload(). It makes it clearer to another developer what you're actually doing. A quick glance at the %Reload() code makes me think that it would be faster than killing the object and calling %OpenId() to reopen it.

Of course, you might want to make use of Concurrency options so that if you have an object open in one process, other processes are prevented from updating it.

This is not quite an answer to your question. Just some clarifications:

  • Your example is a %Query class query, where you write ObjectScript code for the query rather than using SQL. I haven't written one of those for a while. I'm assuming that ROWSPEC and CONTAINID are required for these types of class queries, but I'm not 100% sure.
  • A "newer" way to write a custom ObjectScript-based class query, using the class %SQL.CustomResultSet, doesn't require ROWSPEC either. Sample.CustomResultSet is an example of this technique.
  • For a %SQLQuery class query, written using SQL, ROWSPEC and CONTAINID have not been required for a loooong time. They are dynamically created from the query itself.

This is nice. The only thing I'm wondering about is why there are #dim statements for regular variables? @Timur.Safin, why did you include the #dim statements? In my opinion, #dim statements for variables that are not object references are misleading:

  1. #dim gives developers that are new to ObjectScript the impression that you must declare all variables like in some other languages. Declaring variables like this is not necessary in ObjectScript.
  2. #dim's main purpose is to help Atelier/Studio provide code completion for variables that are object references. If you write this code #dim i as %Integer, and then on the next line you type do i. ,  after the period Atelier/Studio will suggest methods from the %Integer class. If you happen to accept one of the suggestions, the resulting code will not compile. This is because our datatype classes (like %String and %Integer) are not object classes.

Danny and Robert, of course I understand what you are saying (we are the same generation!). Also, I am not trying to be the Developer Community police.

In posts that are asking "what's the recommended way to do this?" we should answer that question. There's no point in mentioning old syntax in that context. Saying "don't do this, but you might see it someday" helps the subset of people that might work with old code, but doesn't help and may confuse the people that are working with new code. It doesn't belong.

On the other hand, if there's a post asking "what are some older/confusing syntaxes I might encounter when working with M or ObjectScript?" we should answer that question. We all have examples of that.

The legacy versions of If and For commands don't use curly braces. But there are no legacy versions of While and Do/While, which require curly braces. So rather than trying to remember which commands use or don't use curly braces, just use curly braces all the time for these, as well as Try/Catch.

Regarding post-conditionals, it's a good habit to put parentheses around the condition, which allows you to put spaces in the condition.

This is valid syntax: set:a=4 y=10

This is valid syntax and more readable: set:(a = 4) y = 10

This is invalid syntax: set:a = 4 y = 10

Regarding the user for Caché/Ensemble processes, the user for those is not always the user that starts/stops Caché/Ensemble. My instance of Ensemble runs on the Mac. For several years, I do a custom install so that I can change the answer to the 4th question below from cacheusr to joelsolon.

User who owns instance: joelsolon
Group allowed to start and stop instance: staff
Effective group for Ensemble processes: cacheusr
Effective user for Ensemble SuperServer: joelsolon

All the Ensemble processes run as OS user joelsolon because of this.

I don't actually have an answer to your question, but maybe these points will help.

One clarification that might help you: the "Ensemble Controller" Service is not an Ensemble process, so the user assigned to that Service doesn't affect what you're asking about. The "Caché/Ensemble Controller" Service is simply something that allows you to start/stop the local Caché or Ensemble. It's just like start/stop on the Launcher (the cube or the E).

It is possible to programmatically add a relationship to two persistent class definitions at runtime, and then compile those classes. That gives you the same result you'd get if you had added the relationship to the class definitions at design time. So I don't think that's what you want.

The term "Relationship" as defined in Caché means "objects of these classes can be linked at runtime, and this relationship will be stored when the objects are saved." So your need to create relationships between persistent objects "as and when they're required" doesn't really match up with this definition. Either a persistent class is in a relationship with another persistent class, or it isn't. It's not possible to have some objects of the class without the relationship definition, and other objects of the class with the relationship definition.

Maybe you just need to substitute one-many relationships for all of your parent-children relationships. One-many relationships are independent; the relationship is not required like it is in parent-children relationships. In v2013.1 and later, you can set the OnDelete action of the one-many relationship to "Cascade" so you get delete behavior similar to parent-children.