· Nov 18, 2021

Create Calculated Property in Persistent Class based on Relationship

Hi Dev Community,

I have a persistent Document class that has a FileName string property and another Question class that has an optional one-to-many relationship with Document.

I'm trying to add a SqlComputed property to the Question class (docFileName) where docFileName = Document.FileName if there is a related Document or an empty string if there isn't one. 

I'd prefer the property to be SqlComputed so that if Question.Document changes, Question.docFileName will automatically update.

Does anyone know the syntax for accessing the properties of a related object in the SqlComputeCode?


Discussion (12)1
Log in or sign up to continue

Here's a possible alternative to using SqlComputeCode.

You can override the getter method for that property so that it always returns the related document name. In your Question class, define your docFileName property as:

Property docFileName As %String [ReadOnly];

You'll want it to be read only because you aren't going to want to be able to set this property in the question object. You're going to want to retrieve it from the document object. If it could also be set here, you'd have things weirdly out of sync. Then, in that same class, include the following method:

Method docFileNameGet() As %String{
    if ..Document '= ""{
        return ..Document.FileName
        return ""

Once you do that, whenever you refer to the question's docFileName, it'll give you the document's file name, or an empty string if there isn't one.

@David Hockenbroch - Thanks for the reply!  

I was looking to create a calculated field since my Question class extends AppS.REST.Model.Adaptor and the JSON returned from the GET request 'api/standard/question' would include the class properties but not their relationships (e.g. Question.Document).

I ended up setting the docFileName property when creating a new Question instance - which seemed to be the easiest/most straightforward way to get the docFileName in the returned JSON. 

it is possible, but I'd rate it as highly inefficient. You have been warned.

working for objects and SQL

/// The company this employee works for.
Relationship Company As Company [ Cardinality = one, Inverse = Employees ];

Property Cname As %String [ Calculated, SqlComputeCode =
    {set {*}=##class(Company).%OpenId({Company}).Name }, SqlComputed ];

Another option 

/// This sample persistent class represents an employee.<br>
Class Sample.Employee Extends Person


/// The company this employee works for.
Relationship Company As Company Cardinality = one, Inverse = Employees ];

Property Cname As %String CalculatedSqlComputeCode = {id,id={%%ID} &sql(select Company->Name into :r from Sample.Employee where %ID=:id{*}=r}, SqlComputed ];