Pergunta
· Abr. 29, 2021

Método de consulta em uma classe %Persistent usando como parâmetro

Olá a todos,

Estou me perguntando se é possível obter os valores de si mesmo para executar uma consulta.

Eu quero criar uma consulta para encontrar um valor em uma classe %Persistent, mas cada uma usa valores diferentes.

Class Kurro.MyClass Extends %Persistent
{

/// Key of process
Property KeyProcess As %String(MAXLEN = "");

/// Specialist
Property CodeSpecialist As %String;

/// Provider
Property CodeProvider As %String;

/// Center
Property CodeCenter As %String;

/// Date
Property Date As %TimeStamp;

/// IdList
Property IdList As %String;

/// IdProcess
Property IdProcess As %String;

/// Duration
Property Duration As %String;

Query GetInfo(pObject AS Kurro.MyClass) As %SQLQuery(CONTAINID = 1, ROWSPEC = "IdList:%String,IdProcess:%String,Duration:%String")
{
    SELECT IdList, IdProcess, Duration
    FROM Kurro.MyClass
    WHERE KeyProcess = :pObject.KeyProcess
    AND CodeSpecialist = :pObject.CodeSpecialist
    AND CodeProvider = :pObject.CodeProvider
    AND CodeCenter = :pObject.CodeCenter
    AND Date = :pObject.Date
}

}

Então eu chamo desta forma:

set obj=##class(Kurro.MyClass).%New()
set obj.KeyProcess="1033004-1#"
set obj.CodeSpecialist = "surgery"
set obj.CodeProvider = "PR002"
set obj.CodeCenter = "CENTER-01"
set obj.Date = $ZDATETIME($ZDATETIMEH("2021-04-30 15:45:00",3,1),3,1)

set result = obj.GetInfoFunc(obj)

Mas eu tenho o seguinte erro

% Message = "ERROR # 5002: Error de cache: <OBJECT DISPATCH> zGetInfoFunc + 5 ^ Kurro.MyClass1 * Propriedade 'KeyProcess' na classe 'Kurro.MyClass' deve ser MultiDimensional"

É estranho, porque essa propriedade é um parâmetro %String simples.

Em seguida, tentei obter valores para si mesmo e chamar usando a mesma instância

Query GetInfo() As %SQLQuery(CONTAINID = 1, ROWSPEC = "IdList:%String,IdProcess:%String,Duration:%String")
{
    SELECT IdList, IdProcess, Duration
    FROM Kurro.MyClass
    WHERE KeyProcess = KeyProcess
    AND CodeSpecialist = CodeSpecialist
    AND CodeProvider = CodeProvider
    AND CodeCenter = CodeCenter
    AND Date = Date
}

e chamá-lo usando

set result = obj.GetInfoFunc()

Mas não funciona

% Message = "ERROR # 5002: Erro de cache: <PARAMETER> z GetInfo + 1 ^ Kurro.MyClass.1"


é possível obter os valores do objeto para usar como parâmetro da consulta?

Atenciosamente,
Kurro

Discussão (5)2
Entre ou crie uma conta para continuar

Talvez passando o ID do objeto em algo parecido com isso:

Query GetInfo(refId As %String) As %SQLQuery(CONTAINID = 1, ROWSPEC = "IdList:%String,IdProcess:%String,Duration:%String")
{
    SELECT list.IdList, list.IdProcess, list.Duration
    FROM Kurro.MyClass list
    JOIN Kurro.MyClass ref on ref.ID = :refId
    AND ref.KeyProcess = list.KeyProcess
    AND ref.CodeSpecialist = list.CodeSpecialist
    AND ref.CodeProvider = list.CodeProvider
    AND ref.CodeCenter = list.CodeCenter
    AND ref.Date = list.Date
}

resposta por @Timothy Leavitt 

É uma boa ideia, mas eu não tem o ID da linha.

Minha ideia era usar o objeto como um parâmetro e passar um monte de valores, e a query leria estes valores, ao invés de passá-los uma a um nos parâmetros.

Eu mudei minha query com todos os parâmetros que eu preciso para executá-la

Query GetInfo(pKeyProcess As %String, pCodeSpecialist As %String, pCodeProvider As %String, pCodeCenter As %String, pDate as %TimeStamp) As %SQLQuery(CONTAINID = 1, ROWSPEC = "IdList:%String,IdProcess:%String,Duration:%String")
{
    SELECT IdList, IdProcess, Duration
    FROM Kurro.MyClass
    WHERE KeyProcess = :pKeyProcess
    AND CodeSpecialist = :pCodeSpecialist
    AND CodeProvider = :pCodeProvider
    AND CodeCenter = :pCodeCenter
    AND Date = :pDate
}

Funciona, mas ainda preciso passar todos os parâmetros. Eu queria criar uma classe para passar todos os parâmetros, tipo um método em c#, e tentar usa-lo.

Valeu galera.

resposta por @Kurro Lopez 

É um assunto interessante.
#2) Seu segundo exemplo não vai funcionar, porque não está passando um parâmetro de chamada.
#1) Não está previsto o uso de propriedades de objetos como variáveis de host em SQL

O código dá erro no método Execute gerado.

set tResult tStatement.%Execute($g(pObject.KeyProcess),$g(pObject.CodeSpecialist),$g(pObject.CodeProvider),$g(pObject.CodeCenter),$g(pObject.Date))

$GET para propriedades de objeto não está implementado. É definido pela classe e está sempre lá. 

Mas é necessário e faz sentido para propriedades multidimensionais!  

Isto é válido para ObjectScript e não está relacionado a SQL.
Mas, escrevendo o código na mão, você pode usar $g(NOTHING,pObject.KeyProcess
O gerador simplesmente não faz isso.
 

Workaround #1: Mexer diretamente no código gerado. Não recomendado.
Workaround #2:  Mova suas propriedades com uma função auxiliar para variáveis locais e ajuste sua query a essas variáveis


example helper (with obj or id):
ClassMethod FillProp(pObject As Kurro.MyClassAs %Boolean SqlName FILLPSqlProc ]
{
if '$isObject(pObjectset obj=##class(Kurro.MyClass).%OpenId(pObject)
else  set obj=pObject
set %Kurro("kp")=obj.KeyProcess
     ,%Kurro("sp")= obj.CodeSpecialist
     ,%Kurro("pr")= obj.CodeProvider
     ,%Kurro("cs")= obj.CodeCenter
    ,%Kurro("dt")= obj.Date
quit 1
}

 

Query exemplo:

Query GetInfoRcc(objid As %IntegerAs %SQLQuery(CONTAINID 0ROWSPEC "IdList:%String,IdProcess:%String,Duration:%String")
{
    SELECT IdListIdProcessDuration
    FROM Kurro.MyClass
    WHERE KeyProcess :%Kurro("kp")
    AND CodeSpecialist :%Kurro("sp")
    AND CodeProvider :%Kurro("pr")
    AND CodeCenter :%Kurro("cs")
    AND "Date" :%Kurro("dt")
   AND FILLP(:objid) = 1
}

Funciona como esperado.

resposta by @Robert Cemper 

Você está implicitamente utilizando o método %Library.SqlQuery:Func(), no qual, como corretamente @Robert Cemper apontou, $get() é usado.

Você pode fazer dessa outra maneira:

Query GetInfo(pObject AS Kurro.MyClassAs %SQLQuery(CONTAINID 1ROWSPEC "IdList:%String,IdProcess:%String,Duration:%String") [ SqlProc ]
{
    SELECT IdListIdProcessDuration
    FROM Kurro.MyClass
    WHERE KeyProcess :pObject.KeyProcess
    AND CodeSpecialist :pObject.CodeSpecialist
    AND CodeProvider :pObject.CodeProvider
    AND CodeCenter :pObject.CodeCenter
    AND "Date" :pObject.Date
}


set obj=##class(Kurro.MyClass).%New()
set obj.KeyProcess="1033004-1#"
set obj.CodeSpecialist "surgery"
set obj.CodeProvider "PR002"
set obj.CodeCenter "CENTER-01"
set obj.Date $ZDATETIME($ZDATETIMEH("2021-04-30 15:45:00",3,1),3,1)

set st=##class(%SQL.Statement).%New()
set sc=st.%PrepareClassQuery("Kurro.MyClass","GetInfo")
  if $$$ISERR(sc{write "%PrepareClassQuery failed:" do $System.Status.DisplayError(scquit}
set result=st.%Execute(obj)
do result.%Display()

resposta por @Vitaliy.Serdtsev