Uma entity selection é um objeto que contém uma ou mais referências a entidades que pertecem à mesma dataclass. Uma entity selection pode conter 0, 1 ou entidades X da dataclass, onde X pode representar a quantidade total de entidades contidas na dataclass.
As seleções de entidade podem ser :
"ordenadas" ou "não ordenadas"
"compartilhável" ou "não compartilhável"
Esses pontos serão analisados abaixo
As entity selections geralmente são criadas utilizando uma pesquisa ou são retornadas desde um atributo relação. Por exemplo:
brokers:=ds.Person.query("personType = broker")
Este código retorna em brokers todas as pessoas de tipo broker. Para acessar a uma entidade da seleção, utilize uma sintaxe similar para acessar a um elemento em uma coleção. Por exemplo:
theBroker:=brokers[0] //As entity selections estão baseadas em 0
O método entitySelection.orderBy( ) retorna uma nova seleção de entidade de acordo com os critérios de classificação fornecidos. Por exemplo:
brokers:=brokers.orderBy("name") //retorna uma seleção ordenada
Este código retorna em brokers a mesma seleção de entidade das entidades Person, mas ordenadas por nome.
Alternativamente, pode usar um atributo relação para devolver uma seleção de entidade. Por exemplo:
Este código atribui a brokerCompanies todas as empresas relacionadas das pessoas na seleção de entidade brokers, utilizando o atributo de relação myCompany. O uso de atributos de relação nas seleções de entidades é uma forma poderosa e fácil de navegar para cima e para baixo a série de entidades relacionadas.
Para realizar ações repetidas a entidades em uma seleção de entidades, como recuperar e modificar valores de certos atributos, pode usar a estrutura For each...End for each. Por exemplo:
C_OBJECT(emp) For each(emp;ds.Employees.all()) If(emp.Country="UK")
emp.salary:=emp.salary*1,03
emp.save() End if End for each
Usando um atributo relação de tipo "related entities" (ver abaixo).
Pode criar e usar simultaneamente tantas entity selections diferentes quantas queira para uma dataclass. Lembre que uma entity selection só contém referências a entidades. As diferentes entity selections podem conter referências às mesmas entidades.
Todos os atributos de armazenamento (texto, número, booleano, data) estão disponíveis como propriedades das entity selections assim como das entidades. Quando for usado junto com uma entity selection, um atributo escalar retorna uma coleção de valores escalares. Por exemplo:
locals:=ds.Person.query("city = :1";"San Jose") //entity selection de people
localEmails:=locals.emailAddress //coleção de endereços de correio eletrônico (strings)
Este código retorna em localEmails uma coleção de endereços de correio eletrônico como strings.
Além da variedade de formas em que pode realizar consultas, também pode usar atributos relação como propriedades de entity selections para devolver novas entity selections. Por exemplo, considere a estrutura abaixo:
myParts:=ds.Part.query("ID < 100") //Retorna partes com ID inferior a 100 $myInvoices:=myParts.invoiceItems.invoice //Todas as faturas com pelo menos uma linha de pedido relacionada com uma parte em myParts
A última linha devolverá em $myInvoices uma entity selection de todas as faturas que tenham pelo menos um item de fatura relacionado com uma parte na entity selection myParts. Quando um atributo relação for usado como uma propriedade de una entity selection, o resultado é sempre outra entity selection, mesmo se apenas for devolvida uma entidade. Quando um atributo relação for usado como uma propriedade de uma entity selection e não forem retornadas entidades, o resultado é uma seleção de entidade vazia, não null.
Uma seleção de entidades pode ser compartilhável (não modificável) ou não compartilhável (modificável).
Uma seleção compartilhável de entidades tem as seguintes características:
pode ser armazenado em um objeto compartilhado ou em uma coleção compartilhada, e pode ser compartilhado entre vários processos ou trabalhadores
pode ser armazenado em vários objetos ou coleções compartilhadas, ou em um objeto ou coleção compartilhada que já pertença a um grupo (não tem um ID de bloqueio).
não permite a adição de novas entidades. A tentativa de adicionar uma entidade a uma seleção de entidades compartilhadas resultará em um erro (1637 - Esta seleção de entidades não pode ser alterada). Para adicionar uma entidade a uma seleção de entidades compartilhadas, você deve primeiro transformá-la em uma seleção de entidades não compartilhadas usando a função entitySelection.copy( ), antes de chamar entitySelection.add( )..
Nota: A maioria das funções de seleção de entidades (such as entitySelection.slice( ), entitySelection.and( )...) são compatíveis com seleções de entida compartilháveis já que não precisam alterar a seleção de entidade original (retornam uma nova).
Uma seleção não compartilhável de entidades tem as seguintes características::
não pode ser compartilhado entre processos, nem armazenado em um objeto ou coleção compartilhada. A tentativa de armazenar uma seleção de entidade não compartilhada em um objeto ou coleção compartilhada resultará em um erro (-10721 - Tipo de valor não suportado em um objeto ou coleção compartilhada)
aceita a adição de novas entidades, ou seja é compatível com a função entitySelection.add( ).
A natureza compartilhável ou alterável da seleção de entidade é definida quando a seleção de entidade for criada (não pode ser modificada depois). Pode achar a natureza de uma seleção de entidade usando a função entitySelection.isAlterable( ) ou o comando OB Is shared.
Uma nova seleção de entidade é compartilhável nos casos abaixo:
Na maioria dos casos, as novas seleções de entidades são compartilháveis, incluindo
a nova seleção de entidades é baseada na relação entity.{attributeName} (por exemplo, empresa.funcionário) quando o atributoNome for um atributo de relação um-para-muitos e a entidade não pertence a uma seleção de entidades
seleções de entidades copiadas explicitamente como sendo compartilhadas com entitySelection.copy( ) ou OB Copy (ou seja a opção ck shared).
Exemplo:
$myComp:=ds.Company.get(2) //$myComp não pertence a uma seleção de entidades $employees:=$myComp.employees //$employees é compartilhavel
Uma nova seleção de entidades é alterável nos casos abaixo:
$toModify:=ds.Company.all().copy() //$toModify é alterável
Uma nova seleção de entidades herda da natureza da seleção de entidade original nos casos abaixo:
a nova seleção de entidade resulta de uma das várias funções de classe ORDA aplicadas a uma seleção de entidade existente (entitySelection.query( ), entitySelection.slice( ), etc.) . A nova seleção de entidade é basea numa relação: entity.{attributeName} (por exemplo empresa/funcionários) quando atributoNome for um atributo de relação um para muitos e a entidade pertencer a uma seleção de entidades (mesma natureza que uma seleção de entidade entity.getSelection( )) entitySelection.{attributeName} (por exemplo. funcionarios/empregador) quando attributeName for um atributo de relação um para muitos (mesma natureza que a seleção de entidade)
entitySelection.extract( ) quando a coleção resultante conter seleções de entidade (mesma natureza que uma seleção de entidade)
Exemplos:
$highSal:=ds.Employee.query("salary >= :1";1000000)&NBSP; //$highSal é compartilhável por causa da pesquisa em dataClass $comp:=$highSal.employer //$comp é partilhável porque $highSal é partilhável
$lowSal:=ds.Employee.query("salary <= :1";10000).copy() //$lowSal is alterable because of the copy() $comp2:=$lowSal.employer //$comp2 é alterável porque $lowSal é alterável
Nota de compatibilidade: é possível "forçar" todas as novas seleções de entidade a serem alteráveis como padrão em seu projeto usando o método dataStore.makeSelectionsAlterable( ). Essa configuração de entidade não é recomendada para novos projetos.
Se trabalhar com duas seleções de entidades que queira passar a um processo worker para que possa enviar correios às pessoas adequadas:
var $paid;$unpaid : cs.InvoicesSelection //criar seleções de entidades para faturas pagadas ou a pagar $paid:=ds.Invoices.query("status=:1";"Paid") $unpaid:=ds.Invoices.query("status=:1";"Unpaid")
//Passamos referências de seleção de entidade como parâmetros ao trabalhador CALL WORKER("mailing";"sendMails";$paid;$unpaid)
]
O método sendMails:
#DECLARE($paid cs.InvoicesSelection;$unpaid cs.InvoicesSelection)
var $invoice : cs.InvoicesEntity
//Loops nas seleções de entidade For each($invoice;$paid) $email.to:=$invoice.customer.address // endereço de email do cliente $email.subject:="Payment OK for invoice # "+String($invoice.number) $status:=$transporter.send($email) End for each
For each($invoice;$unpaid) $email.to:=$invoice.customer.address // endereço de email do cliente $email.subject:="Please pay invoice # "+String($invoice.number) $status:=$transporter.send($email) End for each
As entity selections locais podem ser ordenadas ou não ordenadas. Basicamente, ambos objetos têm uma funcionalidade similar, mas existem algumas diferenças com respeito a seu rendimento e funções disponíveis. Pode decidir que tipo de entity selection usar segundo suas necessidades específicas.
Nota: as Entity selections em uma devolvidas por 4D Server a um cliente remoto sempre são ordenadas.
As entity selections desordenadas são construídas sobre tabelas de bits na memória. Uma entity selection desordenada contém um bit para cada entidade na dataclass, independentemente de se a entidade estiver realmente na seleção. Cada bit é igual a 1 ou 0, para indicar se a entidade estiver ou não incluída na seleção. É uma representação muito compacta para cada entidade. Como consequência, as operações que utilizam entity selections não ordenadas são muito rápidas. Além disso, as entity selections desordenadas são econômicas em termos de espaço de memória. O tamanho de uma entity selection desordenada, em bytes, sempre é igual ao número total de entidades na dataclass dividido entre 8. Por exemplo, se criar uma entity selection desordenada para uma dataclass que contenha 10.000 entidades, ocupará 1.250 bytes, que é aproximadamente 1.2K em RAM. Por outro lado, as entity selections não ordenadas não podem ser ordenadas. Não pode confiar na posição das entidades dentro da seleção. Além disso, não pode ter mais de uma referência à mesma entidade na seleção: cada entidade só pode ser agregado uma vez.
As entity selections ordenadas são criadas sobre arrays inteiros longos (que contenham referências de entidade) na memória. Cada referência a uma entidade toma 4 bytes na memória. Processar e manter essas seleções leva mais tiempo e exige mais espaço de memória que as seleções sem ordenar. Por outro lado, podem ser ordenadas ou reordenar, e pode confiar nas posições da entidade. Além disso, pode agregar mais de uma referência à mesma entidade.
A tabela abaixo resume as principais funcionalidades de cada tipo de entity selection:
Funcionalidade
Entity selection desordenada
Entity selection ordenada
Velocidade de processamento
muito rápido
mais lento
Tamanho na memória
muito pequeno
maior
Pode conter várias referências a uma entidade
não
sim
Por razões de otimização, como padrão normal, 4D ORDA geralmente cria entity selections não ordenadas, exceto quando utilizar o método orderBy( ) ou usar as opções apropriadas (ver a continuação). Nesta documentação, a menos que se especifique "entity selection" geralmente se refere a uma "entity selection desordenada".
Como se mencionou anteriormente, ORDA por padrão cria e maneja entity selections não ordenadas como resultado de operações tais como consultas ou comparações como and( ). As entity selections ordenadas são criadas só quando for necessário ou quando são solicitadas especificamente mediante o uso de opções.
As entity selections ordenadas são criadas nos casos abaixo:
resultado de um orderBy( ) em uma seleção (de qualquer tipo) ou uma orderBy( ) em uma dataclass
resultado do método newSelection( ) com a opção dk keep ordered
As entity selectionsdesordenadas são criadas nos casos abaixo:
resultado de uma query( ) padrão em uma seleção (de qualquer tipo) ou uma query( ) em uma dataclass,
resultado do método newSelection( ) sem opção,
resultado de qualquer um dos métodos de comparação, qualquer que seja o tipo de seleção de entrada: or( ), and( ), minus( ).
Lembre que quando uma entity selection ordenada são convertida em uma entity selection desordenada, qualquer referência de entidade repetida é eliminada.
Se quiser transformar uma entity selection ordenada em uma não ordenada, pode simplesmente aplicar uma operação and( ), por exemplo:
//mySel é uma entity selection ordenada mySel:=mySel.and(mySel) //mySel agora é uma entity selection desordenada
4D oferece uma otimização automática para as petições ORDA que utilizam seleções de entidades ou carregam entidades nas configurações cliente/servidor. Esta otimização acelera a execução de sua aplicação 4D ao reduzir drasticamente o volume de informação transmitida através da rede.
São implementadas os seguintes mecanismos de otimização:
Quando um cliente solicita uma seleção de entidades de servidor, 4D "aprende" automaticamente que atributos da seleção de entidades são utilizadas realmente do lado do cliente durante a execução de código, e cria um "contexto de otimização" correspondente. Este contexto se anexa à seleção de entidades e armazena os atributos utilizados. Se atualizará dinamicamente se depois forem utilizados outros atributos.
As petições posteriores enviadas ao servidor na mesma seleção de entidades reutilizam automaticamente o contexto de otimização e apenas obtém os atributos necessários do servidor, o que acelera o processamento. Por exemplo, em um list box baseado na seleção de entidades, a fase de aprendizagem é feita durante a visualização das primeiras filas, a visualização das filas seguintes está muito otimizada.
Um contexto de otimização existente pode ser passada como uma propriedade a outra seleção de entidades da mesma classe de dados, pelo que se ignora a fase de aprendizagem e se acelera a aplicação (ver abaixo "Uso da propriedade de contexto").
Os métodos abaixo associam automaticamente o contexto de otimização da seleção de entidades de origem à seleção de entidades devolvidas:
$sel:=$ds.Employee.query("firstname = ab@") For each($e;$sel) $s:=$e.firstname+" "+$e.lastname+" works for "+$e.employer.name // $e.employer se refiere a la tabla Company End for each
Graças à otimização, esta solicitude apenas obterá dados dos atributos utilizados (nome, sobrenome, empregador, empregador.nome) em $sel depois de uma fase de aprendizagem.
Utilizando a propriedade de contexto
Pode aumentar os beneficios da otimização utilizando a propriedade contexto. Esta propriedade faz referência a um contexto de otimização "aprendido" para uma seleção de entidades. Se pode passar como parâmetro aos métodos ORDA que devolvem novas seleções de entidades, de modo que as seleções de entidades solicitem diretamente aos atributos utilizados ao servidor e omitem a fase de aprendizagem.
Uma mesma propriedade de contexto de otimização pode ser passada a um número ilimitado de seleções de entidades na mesma classe de dados. Todos os métodos ORDA que manejam as seleções de entidades admitem a propriedad contexto (por exemplo, o método dataClass.query( ) ou dataClass.all( )). Entretanto, lembre que um contexto se atualiza automaticamente quando forem usados novos atributos em outras partes do código. Reutilizar o mesmo contexto em diferentes códigos poderia resultar em uma sobrecarga de contexto e depois reduzir sua eficiência.
Nota: se implementa um mecanismo similar para as entidades que são carregadas, de modo que apenas são solicitadas os atributos utilizados (ver o método dataClass.get( )).
List box baseado na seleção de entidades
A otimização da seleção de entidades se aplica automaticamente aos list boxes baseados em seleção de entidades nas configurações cliente/servidor, ao mostrar e deslocar o conteúdo de um list box. Apenas os atributos mostrados no list box são solicitados desde o servidor. Entretanto, lembre que se utiliza um contexto de otimização diferente quando se carrega a entidade atual da seleção, para não sobrecarregar o contexto de list box.
$sel1:=ds.Employee.query("lastname = S@";$querysettings) $data:=extractData($sel1) // No método extractData, uma otimização é ativada e se associa ao contexto "shortList"
$sel2:=ds.Employee.query("lastname = Sm@";$querysettings) $data:=extractData($sel2) // No método extractData, se aplica a otimização associada ao contexto "shortList"
$sel3:=ds.Employee.query("lastname = Smith";$querysettings2) $data:=extractDetailedData($sel3) // No método extractDetailedData se desencadeia uma otimização e se associa ao contexto "longList"
$sel4:=ds.Employee.query("lastname = Brown";$querysettings2) $data:=extractDetailedData($sel4) //No método extractDetailedData, se aplica a otimização associada ao contexto "longList"
Entretanto, as propriedades entity selection são numeráveis:
ARRAY TEXT($prop;0) OB GET PROPERTY NAMES(ds.Employee.all();$prop) //$prop contém os nomes das propriedades de entity selection //("length", 00", "01"...)