Discussion (14)0
Log in or sign up to continue

@Robert Cemper 

I have a table called TITLE which is generated form a class TITLE in RESTAPI folder so the package is RESTAPI.TITLE and I am creating a new object in another Book class but it has TITLE as a foreign key.

So if I want to insert data in the BOOK class the field for Title in the BOOK class is a foreign key in which is a primary key RowID in the TITLE class.

Given the new object I am creating is this {"ID":17, "Title":"LEARNING CAHE REST API"}

the title field in the BOOK class should give me the RowID which is 2

so in the BOOK class the ID = 17 and Title = 2

That is what I'm trying to work out. 

I'm sorry. it seems you don't understand what I'm talking about.
You just gave me the names. Not the structure and definition. 

Expected example:

Class RestApi.Books Extends %Persistent
{
Property Title As %String;
Property Pages As %Integer; 

Storage Default
{
<Data name="BooksDefaultData">
<Value name="1">
<Value>%%CLASSNAME</Value>
</Value>
<Value name="2">
<Value>Title</Value>
</Value>
<Value name="3">
<Value>Pages</Value>
</Value>
</Data>
<DataLocation>^RestApi.BooksD</DataLocation>
<DefaultData>BooksDefaultData</DefaultData>
<IdLocation>^RestApi.BooksD</IdLocation>
<IndexLocation>^RestApi.BooksI</IndexLocation>
<StreamLocation>^RestApi.BooksS</StreamLocation>
}
}
 
 Class RestApi.Title Extends %Persistent
{
Property Title As Books;
Property Text As %String; 

Storage Default
{
<Data name="TitleDefaultData">
<Value name="1">
<Value>%%CLASSNAME</Value>
</Value>
<Value name="2">
<Value>Title</Value>
</Value>
<Value name="3">
<Value>Text</Value>
</Value>
</Data>
<DataLocation>^RestApi.TitleD</DataLocation>
<DefaultData>TitleDefaultData</DefaultData>
<IdLocation>^RestApi.TitleD</IdLocation>
<IndexLocation>^RestApi.TitleI</IndexLocation>
<StreamLocation>^RestApi.TitleS</StreamLocation>
}
}


it's midnight now. I finish 

maybe next week.

Now, this gets clear.
With the keyword IDKEY you replaced the default ID naming it RowID.

To store it:

set book=##class(BOOK).%New()
set book.RowId=obj.ID     ;  from JSON obj
set book.Title=obj.Title    ;  from JSON obj
do book.%Save()

to retrieve an existing Rowid:

set book=##class(BOOK).%OpenId(obj.ID)   ;from JSON obj
,;; access or change your book.Title

@Robert Cemper 

set book=##class(BOOK).%New()

set book.RowId=obj.ID     ;  from JSON obj

set book.Title=obj.Title    ;  from JSON obj ------->This line causes an OREF error I tried this initially, the Json object is a string eg "CACHE BOOK" and I want to save the RowId in the Title row in BOOK table when creating a new object in book.

do book.%Save()

Retrieving an existing ID I managed to work on that the problem or issue came to creating a new object in BOOK where I have to get RowId inserted into Title field given the obj.Title from postman is a string.

@Robert Cemper 

Hope this is something better.

Class REST.BOOK Extends %Library.Persistent 

{

Property Title As REST.TITLE;

Property Author As %String;

Storage Default

{

<Data name="BOOKDefaultData">

<Value name="1">

<Value>%%CLASSNAME</Value>

</Value>

<Value name="2">

<Value>Title</Value>

</Value>

<Value name="3">

<Value>Author</Value>

</Value>

</Data>

<DataLocation>^REST.BOOKD</DataLocation>

<DefaultData>BOOKDefaultData</DefaultData>

<IdLocation>^REST.BOOKD</IdLocation>

<IndexLocation>^REST.BOOKI</IndexLocation>

<StreamLocation>^REST.BOOKS</StreamLocation>

<Type>%Library.CacheStorage</Type>

}

}

Class RESTAPI.TITLE Extends %Library.Persistent

{

Index IDKeyIndex On RowId [ IdKey, PrimaryKey, Unique ];

Property RowId As %Library.String(COLLATION = "EXACT", TRUNCATE = 0) [ Required, SqlColumnNumber = 1, SqlFieldName = RowId ];

Property Title As %String;

Property Text As %String;

Storage Default

{

<Data name="TITLEDefaultData">

<Value name="1">

<Value>%%CLASSNAME</Value>

</Value>

<Value name="2">

<Value>Title</Value>

</Value>

<Value name="3">

<Value>Text</Value>

</Value>

</Data>

<DataLocation>^REST.TITLED</DataLocation>

<DefaultData>TITLEDefaultData</DefaultData>

<IdLocation>^REST.TITLED</IdLocation>

<IndexLocation>^REST.TITLEI</IndexLocation>

<StreamLocation>^REST.TITLES</StreamLocation>

<Type>%Library.CacheStorage</Type>

}

}

Now with the class definition available, I understand(?) what you are looking for.
I see 2 possible solutions: embedded SQL or an Index on Title
#1

ClassMethod TitleToRowId(title) As %String 
    [ PublicList = (title, rowid, SQLCODE) ]
{
  &SQL(
     SELECT RowId into :rowid 
     FROM REST.TITLE 
      WHERE Title = :title
      )
  if 'SQLCODE quit rowid
  quit SQLCODE
}
 

btw: SQLCODE=0 means success. 
and you get the RowId by 

SET RowId=##class(REST.TITLE).TitleToRowId(obj.Title)  ;obj=JSON
SET task.Title = ##class(RESTAPI.TITLE).%OpenId(RowId)
SET book.Title = ##class(RESTAPI.TITLE).%OpenId(RowId) ; recent example

#2
 creating an Index on Title in REST.TITLE.
 but you have all trouble on duplicates, max. string length on that index
 So I'd position it as elegant but rather risky on maintenance