Usando ProDataSet™ no OpenEdge® 10

Transcrição

Usando ProDataSet™ no OpenEdge® 10
Usando ProDataSet™ no OpenEdge® 10
Luciano Oliveira
Sr. Instructor, Consultant
Global Field Services
Agenda
Origem
ProDataSet Overview
Usando um ProDataSet como informações
de cache
Capturar informações em “Batch” com
ProDataSets
Definições extendidas dos ProDataSet
Mapear um ProDataSet para XML
Conclusão
DEV-9: Using the ProDataSet in OpenEdge 10
2
© 2006 Progress Software Corporation
Parâmetro Temp-Table
Definir uma temp-table
• Baseado em tabelas do banco ou não
Popular uma temp-table no servidor
• Uma linha ou mais
Passar a temp-table como parâmetro
• Um parâmetro por tabela
Modificar a temp-table no client e retorná-la
DEV-9: Using the ProDataSet in OpenEdge 10
3
© 2006 Progress Software Corporation
Limitação Temp-Table
Tabela separada e parâmetro para cada
definição de informação bidimensional
Pai-Filho e outros relacionamentos
necessários por vários parâmetros
Nenhum mecanismo padrão para gravar
mudanças
DEV-9: Using the ProDataSet in OpenEdge 10
4
© 2006 Progress Software Corporation
A direção
Definir um núcleo único de objeto no OpenEdge
para representar dados com relacionamentos
complexos
• Um handle, um parâmetro
Validação associada e outras lógicas de negócios
• Eventos internos
Mapear diretamente para objetos de dados de
outras tecnologias
DEV-9: Using the ProDataSet in OpenEdge 10
5
© 2006 Progress Software Corporation
ProDataSet para ADO.NET DataSet
ProDataSet é um objeto OpenEdge
armazenado na memória
ProDataSet mapeia diretamente para um
ADO.NET DataSet, permitindo que você:
• Construa uma interface .NET™ nos padrões
.NET DataSets
• Passar e receber dados utilizando OpenEdge
AppServer™
ProDataSet também mapeia para Java™ e
SDO em OpenEdge 10.1A
DEV-9: Using the ProDataSet in OpenEdge 10
6
© 2006 Progress Software Corporation
Agenda
Origem
ProDataSet Overview
Usando um ProDataSet como informações
de cache
Capturar informações em “Batch” com
ProDataSets
Definições extendidas dos ProDataSet
Mapear um ProDataSet para XML
Conclusão
DEV-9: Using the ProDataSet in OpenEdge 10
7
© 2006 Progress Software Corporation
Um ProDataSet é composto por Temp-Tables
Definição de temp-tables
DEFINE TEMP-TABLE ttOrder
/* fields from Order db table */
FIELD OrderTotal AS DECIMAL
FIELD CustName LIKE Customer.Name
FIELD RepName
LIKE SalesRep.RepName.
DEFINE TEMP-TABLE ttOrderLine…
DEFINE TEMP-TABLE ttItem…
DEV-9: Using the ProDataSet in OpenEdge 10
8
© 2006 Progress Software Corporation
Definição do DataSet
Definir um DataSet nos padrões de Temp-Table
DEFINE DATASET dsOrder FOR ttOrder, ttOline, ttItem
DATA-RELATION OrderLine FOR ttOrder, ttOline
RELATION-FIELDS (OrderNum, OrderNum)
DATA-RELATION LineItem FOR ttOline, ttItem
RELATION-FIELDS (ItemNum, ItemNum) REPOSITION.
DEV-9: Using the ProDataSet in OpenEdge 10
9
© 2006 Progress Software Corporation
Data-Relations
O Data-Relation define o relaciomento entre
tabelas Pai-Filho
O Relation-Fields define campos nas tabelas
para construir as consultas
…DATA-RELATION OrderLine FOR ttOrder, ttOline
RELATION-FIELDS (OrderNum, OrderNum)…
Relation-Fields são utilizadas para
determinar como popular o DataSet
Eles também dizem ao OpenEdge como
navegar no DataSet
DEV-9: Using the ProDataSet in OpenEdge 10
10 © 2006 Progress Software Corporation
Data-Sources informam ao OpenEdge a origem da
informação
O Data-Source é um objeto separado do
ProDataSet
Definir um Data-Source para cada buffer de temptable no DataSet
Cada Data-Source pode definir buffer, query ou
ambos
DEV-9: Using the ProDataSet in OpenEdge 10
11 © 2006 Progress Software Corporation
Populando um ProDataSet
Utilize o método FILL para popular o DataSet de um
Data-Source
FILL nos DataSet preênchem toda tabela seguindo a
ordem dos buffers
FILL em um buffer preenche uma tabela descendente
FILL-MODE
• NO-FILL – pula a tabela
• EMPTY – esvazia a tabela
• APPEND – adiciona mais registros para tabela
• MERGE – adiciona registro & elimina cópia
• REPLACE – sobrepõe registro
DEV-9: Using the ProDataSet in OpenEdge 10
12 © 2006 Progress Software Corporation
Populando com Data-Relations
…DATA-RELATION OrderLine FOR ttOrder, ttOline
RELATION-FIELDS (OrderNum, OrderNum)…
Quando um DataSet é populado, OpenEdge
captura os “filhos” dos “pais”
ProDataSet
Order
Data-Source
OrderTT
6
36
79
01/05/93
01/19/93
02/10/93
Data-Relation
Application
Database
1
1
1
OrderLineTT
Order
Data-Source
DEV-9: Using the ProDataSet in OpenEdge 10
6
6
6
1
2
3
00009
00009
00011
36
36
36
1
2
3
00009
00009
00011
13 © 2006 Progress Software Corporation
Event Callback Procedures
Você pode definir eventos para:
Antes e Depois FILL do ProDataSet
• Antes e Depois do FILL de alguma temp-table
• Antes e Depois do FILL de algum registro
Use os eventos ProDataSet para preparar
queries, atachar Data-Sources, etc.
Use eventos de Buffer para manipular a tabela
Use eventos de Record para calcular campos
Você pode usar estes eventos quando não
houver Data-Sources
DEV-9: Using the ProDataSet in OpenEdge 10
14 © 2006 Progress Software Corporation
ProDataSets Dinâmico
Todos elementos de um ProDataSet podem ser
dinâmicos
• CREATE DATASET
• ADD-BUFFER()
• ADD-RELATION()
Um Data-Source também podem ser dinâmicos:
• CREATE DATA-SOURCE
Um DataSet pode usar temp-tables dinâmicas
• CREATE TEMP-TABLE
Atributos e métodos podem ser utilizados num
DataSet através de seu Handle
DEV-9: Using the ProDataSet in OpenEdge 10
15 © 2006 Progress Software Corporation
Atualizar com o ProDataSet
ProDataSet tem ajuda no momento da
gravação, o before-image da temp-table para
esse auxílio (add/change/delete)
• Utilizado para passar alterações para o
servidor feitas pelo Data-Source
• Mapear para objetos .NET e Java – versões
atualizadas
DEV-9: Using the ProDataSet in OpenEdge 10
16 © 2006 Progress Software Corporation
Before-Image Table para um DataSet
Valores originais para todos registros modificados
Valores iniciais para todos registros adicionados
Valores iniciais para todos registros excluídos
ProDataSet
OrderTT
6
36
79
1
1
1
01/05/93
01/19/93
02/10/93
Data-Relation
OrderLineTT
DEV-9: Using the ProDataSet in OpenEdge 10
6
6
6
6
1
2
3
4
00009
00010
00011
00077
0
6
6
0
2
5
00000
00009
00022
A
M
D
17 © 2006 Progress Software Corporation
Salvando alterações para o Banco de Dados
SAVE-ROW-CHANGES é um método para
salvar a “linha” para o Banco de Dados
• Use a before-table para tratar o LOCK
• Permite total controle de conflito através de
eventos
ERROR, ERROR-STRING, REJECTED, DATASOURCE-MODIFIED - Atributos
DEV-9: Using the ProDataSet in OpenEdge 10
18 © 2006 Progress Software Corporation
Resumindo ProDataSet
Objeto avançado de dados construídos com
Temp-Table e seus relacionamentos
Separar o Data-Source para definir os dados
físicos
FILL automatiza e suporta navegação no
objeto
Atualização dentro do ProDataSet
Suporta voltar informações salvas em um
Data-Source
DEV-9: Using the ProDataSet in OpenEdge 10
19 © 2006 Progress Software Corporation
DEV-9: Using the ProDataSet in OpenEdge 10
20 © 2006 Progress Software Corporation
Agenda
Origem
ProDataSet Overview
Usando um ProDataSet como informações
de cache
Capturar informações em “Batch” com
ProDataSets
Definições extendidas dos ProDataSet
Mapear um ProDataSet para XML
Conclusão
DEV-9: Using the ProDataSet in OpenEdge 10
21 © 2006 Progress Software Corporation
Passando um ProDataSet como um Parâmetro
Você pode passar um parâmetro DataSet como:
• DATASET – referência estática como uma
Tabela
• DATASET-HANDLE – referência dinâmica para
um DataSet e suas definições, como TABLEHANDLE – passa um simples handle DataSet
para uma procedure
Anote!
• É padrão o DATASET e o DATASET-HANDLE
criarem uma cópia do conteúdo de um ProDataSet.
DEV-9: Using the ProDataSet in OpenEdge 10
22 © 2006 Progress Software Corporation
Passando um ProDataSet BY-REFERENCE:
Local para uma sessão
RUN OrderDset.p ON hSession
(INPUT iOrderNum,
OUTPUT DATASET dsOrder
BY-REFERENCE).
ProDataSet
OrderTT
6
36
79
1
1
1
01/05/93
01/19/93
02/10/93
/* OrderDset.p -- Test proc for Order Dataset */
{dsOrderTT.i}
{dsOrder.i}
DEFINE INPUT
PARAMETER iOrderNum AS INTEGER.
DEFINE OUTPUT PARAMETER DATASET
DEV-9: Using the ProDataSet in OpenEdge 10
FOR dsOrder.
23 © 2006 Progress Software Corporation
Remoto DataSet BY-REFERENCE
RUN OrderDset.p ON
hSession(INPUT iOrderNum,
OUTPUT DATASET dsOrder
BY-REFERENCE).
ProDataSet
/* OrderDset.p */
DEFINE OUTPUT PARAMETER
DATASET FOR dsOrder.
ProDataSet
OrderTT
OrderTT
6
36
79
1
1
1
01/05/93
01/19/93
02/10/93
DEV-9: Using the ProDataSet in OpenEdge 10
6
36
79
1
1
1
01/05/93
01/19/93
02/10/93
24 © 2006 Progress Software Corporation
Ilustração de uma chamada BY-REFERENCE
DEFINE DATASET dsRef… holds data
DEFINE DATASET dsRef…
unused
dsRef:FILL().
RUN fetchData IN hProc2
(OUTPUT DATASET dsRef
BY-REFERENCE).
PROCEDURE fetchData:
DEFINE OUTPUT PARAMETER
FOR DATASET dsRef.
dsRef:FILL().
END PROCEDURE.
Sempre o programa que chama utiliza a instância
Procedure chamada instância um ProDataSet que
nunca foi utilizado
Referências são redirecionadas para a duração
daquela chamada
DEV-9: Using the ProDataSet in OpenEdge 10
25 © 2006 Progress Software Corporation
Novas opções de parâmetros no 10.1A:
Usando ProDataSet para caching de dados
Define DATASET dsRef
REFERENCE-ONLY…
unused
RUN bindData IN hProc2
(OUTPUT DATASET dsRef BIND)
RUN fetchData IN hProc2.
DISPLAY <dsRef fields>.
Define DATASET dsRef…
data cache
PROCEDURE bindData:
DEFINE OUTPUT PARAMETER
FOR DATASET dsRef BIND.
END PROCEDURE.
PROCEDURE fetchData:
dsRef:FILL().
ProDataSet – or temp-table – em um lado a chamada
é REFERENCE-ONLY
Use a opção BIND em ambos os lados de uma
chamada de procedure
Não precisa passar o ProDataSet novamente!
DEV-9: Using the ProDataSet in OpenEdge 10
26 © 2006 Progress Software Corporation
Resumo de BY-REFERENCE e BIND
Use BY-REFERENCE para usar o
ProDataSet de quem chamou no programa
chamado
Use REFERENCE-ONLY para instâncias
pouco utilizadas
Use BIND para indentificar instâncias
chamadas ou chamadoras
BIND é útil para caching dos dados e
separação da gerência dos dados em relação
a interface do usuário
DEV-9: Using the ProDataSet in OpenEdge 10
27 © 2006 Progress Software Corporation
Agenda
Origem
ProDataSet Overview
Usando um ProDataSet como informações
de cache
Capturar informações em “Batch” com
ProDataSets
Definições extendidas dos ProDataSet
Mapear um ProDataSet para XML
Conclusão
DEV-9: Using the ProDataSet in OpenEdge 10
28 © 2006 Progress Software Corporation
Batching no ambiente distribuído stateless
AppServer
Client
Database
QUERY CustBrowse
PROCEDURE offEnd:
dsCustomer
BATCH-SIZE
APPEND
OFF-END event
PROCEDURE fetchCustomers:
RUN fetchWhere ON hAppServer
dsCustomer
LAST-BATCH
NEXT-ROWID
Procedure fetchWhere:
RESTART-ROWID
DATASET dsCustomer:FILL()
(OUTPUT DATASET dsCustomer) APPEND)
DEV-9: Using the ProDataSet in OpenEdge 10
29 © 2006 Progress Software Corporation
Eventos de ProDataSet para data batching
O objetivo é fazer a recuperação de dados
com batching
OFF-END - Evento para uma Query
ProDataSet
• Ocorre quando a Query vai para o Fim
• Ocorre antes Browse:OFF-END
• Ocorre antes Query:QUERY-OFF-END
FIND-FAILED para encontrar no buffer
• Responder se há linhas faltando
DEV-9: Using the ProDataSet in OpenEdge 10
30 © 2006 Progress Software Corporation
Simples código para Batching
Configurar o handle para o evento OFF-END
QUERY CustBrowse:SET-CALLBACK(“OFF-END”, “OffEnd”).
Define o evento
PROCEDURE OffEnd:
DEFINE INPUT PARAMETER DATASET FOR dsCustomer.
IF NOT BUFFER eCustomer:LAST-BATCH THEN
DO:
RUN fetchCustomers.
RETURN NO-APPLY. /* Cancel OFF-END */
END.
END PROCEDURE.
DEV-9: Using the ProDataSet in OpenEdge 10
31 © 2006 Progress Software Corporation
Solicitando um batch para o Servidor
Criar a solicitação
RUN fetchWhere ON hServer
(INPUT “Customer”, INPUT iBatchSize,
INPUT-OUTPUT rRestartRowid,
INPUT cWhereString,
OUTPUT DATASET dsCustomer APPEND).
Handle da solicitação para o Servidor
hCustBuffer:BATCH-SIZE = iBatchSize.
hDataSource:RESTART-ROWID(1) = rRestartRowid.
hCustQuery:QUERY-PREPARE(“FOR EACH Customer WHERE “
+ cWhereString).
DATASET dsCustomer:FILL().
IF hCustBuffer:LAST-BATCH = NO THEN
rRestartRowid = hDataSource:NEXT-ROWID(1).
DEV-9: Using the ProDataSet in OpenEdge 10
32 © 2006 Progress Software Corporation
DEV-9: Using the ProDataSet in OpenEdge 10
33 © 2006 Progress Software Corporation
Agenda
Origem
ProDataSet Overview
Usando um ProDataSet como informações
de cache
Capturar informações em “Batch” com
ProDataSets
Definições extendidas dos ProDataSet
Mapear um ProDataSet para XML
Conclusão
DEV-9: Using the ProDataSet in OpenEdge 10
34 © 2006 Progress Software Corporation
Utilizando novas sintaxes ABL no OpenEdge 10.1A
misturando referências dinâmicas e estáticas
OpenEdge 10.0:
hDataSet:GET-BUFFER-HANDLE(“ttOrder”)
hDataSet:GET-BUFFER-HANDLE(“ttOrder”):BUFFERFIELD(“OrderNum”):BUFFER-VALUE
hOrderBuf:BUFFER-FIELD(“OrderNum”):BUFFER-VALUE
Argumentos para métodos podem ser
expressões
1 TO NUM-BUFFERS or NUM-FIELDS
• pcBufferName or pcFieldName
Suporta acesso dinâmico, temp-tables, e
ProDataSets
DEV-9: Using the ProDataSet in OpenEdge 10
35 © 2006 Progress Software Corporation
Quando utlizar uma combinação de Dinâmico e
Estático
As vezes você pode saber os nomes dos
buffers no ProDataset ou o nome do campo
no buffer.
Mas você pode não saber o nome exato do
Buffer ou a definição
• A mesma lógica pode ser utlizada para
ProDatasets compartilhados
• Ou para vários buffers que compartilham o
mesmo buffer
hDataSet:GET-BUFFER-HANDLE(“ttOrder”)
DEV-9: Using the ProDataSet in OpenEdge 10
36 © 2006 Progress Software Corporation
Fornecendo argumentos conhecidos para
referências dinâmicas no OpenEdge 10.1A
Em vez de toda essa sintaxe:
hDataSet:GET-BUFFER-HANDLE(“ttOrder”):
BUFFER-FIELD(“OrderNum”):BUFFER-VALUE
No 10.1A você pode codificar:
hDataSet::ttOrder::OrderNum
Dynamic reference
Literal value
Etc…
Double colon!
DEV-9: Using the ProDataSet in OpenEdge 10
37 © 2006 Progress Software Corporation
Sintaxes
hDataSet::ttOrder
Fields the buffer handle for the temp-table ttOrder
hDataSet::ttOrder::OrderNum
Fields the field value for the field OrderNum in ttOrder
Note the second ‘::’ because ttOrder yields a handle
hBuffer::OrderNum
Fields the field value for the field OrderNum
Note that you get the BUFFER-FIELD value, not the field handle
DEV-9: Using the ProDataSet in OpenEdge 10
38 © 2006 Progress Software Corporation
Por que você precisa de referências literais
dos HANDLES?
PROCEDURE eItemAfterRowFill:
DEFINE INPUT PARAMETER DATASET-HANDLE phDataSet.
DEFINE VARIABLE cItemTypes AS CHAR INIT
“BASEBALL,CROQUET,FISHING,FOOTBALL,GOLF,SKI,SWIM”.
DO iType = 1 TO NUM-ENTRIES(cItemTypes):
cType = ENTRY(iType, cItemTypes).
IF INDEX(phDataSet::eItem::ItemName, cType)
NE 0 THEN
phDataSet::eItem::ItemName =
REPLACE(phDataSet::eItem::ItemName,
cType, cType).
END.
END PROCEDURE.
DEV-9: Using the ProDataSet in OpenEdge 10
39 © 2006 Progress Software Corporation
Resumo das novas sintaxes
Deixa-o codificar referências estáticas de um
Handle
Utilize para Lógica de Negócios com variáves,
definindo ProDataSet e temp-table
Utilize com definições extendidas
DEV-9: Using the ProDataSet in OpenEdge 10
40 © 2006 Progress Software Corporation
Agenda
Origem
ProDataSet Overview
Usando um ProDataSet como informações
de cache
Capturar informações em “Batch” com
ProDataSets
Definições extendidas dos ProDataSet
Mapear um ProDataSet para XML
Conclusão
DEV-9: Using the ProDataSet in OpenEdge 10
41 © 2006 Progress Software Corporation
Por quê você deve se importar com dados XML?
XML representa dados no formato caracter
• Mantém os dados independente do Banco de Dados
• Contexto ou outros dados fora do DB
• XML é um formato padrão para troca de dados
– Web services e outras integrações
• XML para Integração em camadas usando
Arquitetura de Referência
DEV-9: Using the ProDataSet in OpenEdge 10
42 © 2006 Progress Software Corporation
Convertendo entre XML e ProDataSets
Novos métodos de ProDataSet (e temp-table)
em OpenEdge 10.1A:
• READ-XML – Lê o XML e carrega-o para o
ProDataSet
– Pode ser criado após a definição do
ProDataSet e do comando CREATE DATASET
• READ-XMLSCHEMA – cria ou verifica
informações do esquema XML
• WRITE-XML – cria stream XML dos dados
• WRITE-XMLSCHEMA – cria informações de
esquema do XML baseado nas definições de
dados
DEV-9: Using the ProDataSet in OpenEdge 10
43 © 2006 Progress Software Corporation
Exemplo - WRITE-XML writeOrder.p
DEFINE DATASET dsOrder FOR eOrder, eOrderLine
DATA-RELATION OrderLine FOR eOrder, eOrderLine
RELATION-FIELDS (OrderNum, OrderNum).
hOrderBuf = DATASET dsOrder::eOrder.
hOlineBuf = DATASET dsOrder::eOrderLine.
hOrderBuf:ATTACH-DATA-SOURCE(DATA-SOURCE
srcOrder:HANDLE, “Customer.Name,CustName”).
hOlineBuf:ATTACH-DATA-SOURCE(DATA-SOURCE
srcOline:HANDLE,””).
QUERY OrderQuery:QUERY-PREPARE(“FOR EACH Order WHERE…).
DATASET dsOrder:FILL().
DATASET dsOrder:WRITE-XML (“FILE”,”dsOrder.xml”, TRUE).
DEV-9: Using the ProDataSet in OpenEdge 10
44 © 2006 Progress Software Corporation
O resultado XML
DEV-9: Using the ProDataSet in OpenEdge 10
45 © 2006 Progress Software Corporation
Resumo do ProDataSet-to-XML
Auto-convert do ProDataSet ou temp-table
para XML
Opcionalmente gera schema
Auto-convert dados XML para uma temptable ou ProDataSet
Opcionalmente gera definições
dinamicamente criadas
DEV-9: Using the ProDataSet in OpenEdge 10
46 © 2006 Progress Software Corporation
OpenEdge 10.1A - Depoimento
!
"
#
$
%
()$
&
'
*
Jeffrey Kodman ,
Manuvis
DEV-9: Using the ProDataSet in OpenEdge 10
47 © 2006 Progress Software Corporation
Agenda
Origem
ProDataSet Overview
Usando um ProDataSet como informações
de cache
Capturar informações em “Batch” com
ProDataSets
Definições extendidas dos ProDataSet
Mapear um ProDataSet para XML
Conclusão
DEV-9: Using the ProDataSet in OpenEdge 10
48 © 2006 Progress Software Corporation
Resumo – O que você deve saber?
Como construir ProDataSets para dados
complexos, relacionamentos e data sources
Como mapear para .NET e outras plataformas
Como manter e gerenciar atualizações utilizando
ProDataSets
Como extender sua lógica com eventos
Como compartilhar instâncias de um ProDataSet
Como criar "data batching”
Como “mixar” referências dinâmicas e estáticas
Como utilizar XML para integração
DEV-9: Using the ProDataSet in OpenEdge 10
49 © 2006 Progress Software Corporation
Materiais disponíveis no PSDN
DEV-9: Using the ProDataSet in OpenEdge 10
50 © 2006 Progress Software Corporation
Conclusão…
ProDataSet é um recurso chave em
aplicações OpenEdge 10
É fundamental para organizar dados
complexos, definições e Lógica de Negócio
em ABL
• …Adaptado ao OpenEdge Reference
Architecture
ProDataSet é um standards-conformant que
integra com .NET, Sonic e Web services
como parte de Service-Oriented Architecture
DEV-9: Using the ProDataSet in OpenEdge 10
51 © 2006 Progress Software Corporation
Recursos adicionais
Expert Series book: Using ProDataSets
• Disponível no amazon.com!
PSDN white paper on Using Advanced
ProDataSet Language Features
• Parte da implementação OERA
PSDN “patterns” papers on topics
Two-day instructor-led or self-study course:
Using ProDataSets
OpenEdge online documentation
DEV-9: Using the ProDataSet in OpenEdge 10
52 © 2006 Progress Software Corporation
Progress Education
Para saber mais sobre este assunto consulte
informações do treinamento
Using ProdataSets
no nosso stand de treinamento.
DEV-9: Using the ProDataSet in OpenEdge 10
53 © 2006 Progress Software Corporation
Dúvidas?
DEV-9: Using the ProDataSet in OpenEdge 10
54 © 2006 Progress Software Corporation
Pela atenção,
obrigado!
DEV-9: Using the ProDataSet in OpenEdge 10
55 © 2006 Progress Software Corporation
DEV-9: Using the ProDataSet in OpenEdge 10
56 © 2006 Progress Software Corporation

Documentos relacionados

Interfaces de Serviço na Prática

Interfaces de Serviço na Prática Conecta-se ao AppServer Passa o Id da Sessione e outras informações de contexto Passa parâmetros para a requisição

Leia mais

Gerenciamento e Replicação OpenEdge® – Divide et impera!

Gerenciamento e Replicação OpenEdge® – Divide et impera! 10 COMP-10: OpenEdge Management & Replication – Divide et impera!

Leia mais