Pregunta
Kurro Lopez · Abr 28, 2021

Método de consulta en una clase %Persistent usándose a sí mismo como parámetros

Hola todos,

Me pregunto si es posible obtener los valores de sí mismo para ejecutar una consulta.

Quiero crear varias QUERY para encontrar un valor en una clase %Persistent pero cada una 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
}

}

Entonces lo llamo de esta manera:

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)

Pero tengo el siguiente error

%Message = "ERROR #5002: Error de cache: <OBJECT DISPATCH>zGetInfoFunc+5 ^Kurro.MyClass1 * La propiedad 'KeyProcess' en la clase 'Kurro.MyClass' debe ser multidimensional"

Es extraño, porque esta propiedad es un parámetro %String simple.

Luego, intenté obtener los valores propios de la clas y llamar usando la misma instancia

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
}

y llámalo usando esta sentencia

set result = obj.GetInfoFunc()

Pero no funciona

%Message = "ERROR # 5002: Error de cache: <PARAMETER> zGetInfo + 1 ^Kurro.MyClass.1"


¿Es posible obtener los valores del objeto para usarlo como parámetro de la consulta?

Atentamente,
Kurro

Product version: HealthShare 2017.2
$ZV: Cache for Windows (x86-64) 2017.2.1 (Build 801_3U) Thu Apr 12 2018 10:02:23 EDT
0
0 45
Debate (2)2
Inicie sesión o regístrese para continuar

¿Tienes un repo en GitHub para clonarlo y hacer alguna prueba? Así será más fácil

Hola,

Os comento las respuestas obtenidas en el community en inglés. Adjunto también el enlace a la respuesta original.

Respuesta de @Robert Cemper 
https://community.intersystems.com/post/query-method-class-persistent-us...

#2) El segundo ejemplo no puede funcionar, principalmente porque no pasa un parámetro en la llamada

#1) NO está previsto utilizar propiedades de objeto vomo variables del lengiaje principal en SQL

El código falla en el métode Execute generado

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

El método $GET object-property simplemente no está implementado. Está definido por la clase y siempre está ahí, pero es necesario y tiene sentido para propiedades multidimensionados

Esto es válido para ObjectScript como tal y no está relacionado con SQL.
Es como tener un método $g(NOTHING, pObkect.KeyProcess)... osea, nada

Alternativas:

  1. Manipular directamente el código generado. No recomendado
  2. Mover las propiedades con una función auxiliar a variables loclaes y ajusta la consulta con esas variables
ClassMethod FillProp(pObject As Kurro.MyClass) As %Boolean [ SqlName = FILLP, SqlProc ]
{
if '$isObject(pObject) set 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
}

Y la invocación sería de esta forma:

Query GetInfoRcc(objid As %Integer) As %SQLQuery(CONTAINID = 0, ROWSPEC = "IdList:%String,IdProcess:%String,Duration:%String")
{
    SELECT IdList, IdProcess, Duration
    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
}

Respuesta de @Vitaliy.Serdtsev 
https://community.intersystems.com/post/query-method-class-persistent-us...

Tal y como ha comentado Robert, el problema está en el $GET(), por lo que en lugar de utilizar el método %Library.SqlQuery:Func(), utilizar el PrepareClaseQuery

Query GetInfo(pObject AS Kurro.MyClass) As %SQLQuery(CONTAINID = 1, ROWSPEC = "IdList:%String,IdProcess:%String,Duration:%String") [ SqlProc ]
{
    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
}


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(sc) quit}
set result=st.%Execute(obj)
do result.%Display()

He utilizado la última respuesta para solucionar mi problema y funciona muy bien

Mucha gracias a los dos por estas respuestas.

Un saludo,
Kurro