Resumo da Sessão "Effective Geodatabase Programming" do Esri DevSummit 2012

Post on 12-Jul-2015

282 views 21 download

Transcript of Resumo da Sessão "Effective Geodatabase Programming" do Esri DevSummit 2012

Resumão da Sessão Técnica

Effective Geodatabase Programming By Craig Gillgrass, Erik Hoel

Bruno CaimarImagem Soluções Verticais

Abril / 2012

Atenção:

Essa apresentação foi criada com base em minhas anotações da apresentação desse ano e nos slides da apresentação do DevSummit de 2011 que podem ser

obtidos em:

http://bit.ly/JoaoHv

Essa não é uma sessão introdutória

Nós assumimos que:

* Possuem conhecimento pratico de Geodatabase e alguma experiencia em desenvolvimento utilizando a API

* Códigos de exemplos em Java e C#

* Muito conteúdo técnico, pouco tempo

* Best practices / Questões comuns

Resumo

• Instâncias únicas de objetos

• Cursores

• Schema Cache

• Geodatabase Schema Simplificado

• Erros mais comuns (Do not do list)

Instâncias únicas de objetos

• Objetos de geodatabase que possuem SEMPRE no máximo uma instância- São similares a objetos COM Singletons exceto que eles não são 'cocreateables'- Exemplos:- Datasets (tables, feature classes, feature datasets)

- Workspaces e Versions

• Independente da API que retornou a referência, ela é SEMPRE a mesma referência

* Alterações em um objeto AFETAM todos outros que contem referência para o mesmo

Instâncias únicas de objetos

Instâncias únicas de objetosCaso especial

Rows\Features são instâncias únicas apenas em sessões de edição

Cursores Três tipos de classes de cursores - Search (Cursor de busca em geral) - Update (Cursor de atualização posicional) - Insert (Cursor de inclusão em bloco)

Um cursor 'QueryDef' - Consulta definida (e.g., IQueryDef.Evaluate)

Qual a diferença? * Linhas criadas por cursores de classes são vinculadas a classe que criou o cursor * Linhas criadas por cursores 'QueryDef' não são vinculadas a uma classe

Cursores - Exemplo

Cursores - Consulta

Todas as classes baseadas na API de consulta- API's comuns que criam cursores de consulta (search)- ITable.Search / GetRow / GetRows, ISelectionSet.Search

Em uma sessão de edição, a consulta pode ser atendida por uma cache (spatial cache, object pool)

• Utilizando em uma sessão de edição irá liberar (flush) as linhas cacheadas (apenas da classe)- Pode resultar em uma gravação no banco de dados

Linhas consultadas podem ser modificadas- Store/Delete suportados

Cursores - Atualização• Cursores de atualização posicional - NextRow->UpdateRow …NextRow->UpdateRow - Atualiza a linha na posição corrente do cursor

• APIs comuns para criação de cursores de atualização - ITable.Update, ISelectionSet2.Update

• A consulta NUNCA é atendida por um cache

• Utilizando em uma sessão de edição irá liberar (flush) as linhas cacheadas da classe em questão

• Linhas consultadas podem ser modificadas utilizando-se ICursor.UpdateRow ou ICursor.DeleteRow

- Store e Delete NÃO devem ser utilizados

Cursores - Atualização• Se a classe suportar os eventos de 'Store' então... - Um cursor interno é criado e UpdateRow e DeleteRow se

tornam equivalentes a Row.Store e Row.Delete

• Como saber? - Feature types não simples (!esriFTSimple) - Classes participantes em uma Geometric Network,

Relationships que requerem mensagens - Features customizadas (ObjectClassExtension overrides)

• Comportamento do método UpdateRow - Erro se chamado em uma linha (row) que não foi obtida de

um cursor de atualização - Erro se chamado em uma linha (row) for da posição atual

do cursor

Cursores - Atualização Melhores Práticas

• Não utilize um cursor de atualização entre operações de edição (uma exceção será lançada a partir do 10.0)

- isso é MUITO importante quando se está editando dados versionados

• Cursores de atualização 'apontam' para uma estado especifico do banco de dados

- Esse estado pode alterado durante sessões de edição - Alterações podem ser perdidas • Best Practice: SEMPRE mantenha seu cursor de

atualização dentro do escopo de uma operação de edição - se você iniciar uma nova operação de edição você DEVE

iniciar um novo cursor de atualização

Cursores - Inclusão

• Recomendado para inclusões em massa (bulk insert)

• API para criar um cursor de inclusão - ITable.Insert

• Melhor performance quando utilizado com buffer e flush apropriados

• Se a classe suportar eventos de 'Store' então InsertRow internamente se tornará um CreateRow e Store

Cursores – Inclusão - Buffering

• Passar 'true' no argumento “useBuffering” do método ITable.Insert

• Periodicamente chamar o Flush - 1000 linhas por vez é um bom número para começar - Quanto maior o intervalo de flush menor o trafego de rede

(mas maior o trabalho de re-inclusão, se necessário)

• Certifique-se que a classe não possua cache espacial – processamento extra é requerido para manter o cache sincronizado

• IMPORTANTE: as chamadas tanto para InsertRow e Flush devem possuir tratamento de erro adequado porque ambos podem resultar em escrita no banco de dados

Buffering com Enterprise GeoDB's

Buffering com Enterprise GeoDB's

Cursores – QueryDef

• Executam query's definidas pelo usuário (não ligadas a classes)

• Cursores QueryDef nunca utilizam qualquer tipo de cache (classe ou workspace)

• Chamada de IQueryDef.Evaluate dentro de um sessão de edição irá provocar um 'flush' de todas as linha em cache

• Linhas retornadas por esse tipo de cursor não suportam modificação (Store e Delete)

O que são Recycling Cursors?

• Um “recycling cursor” é um cursor que não cria um novo objeto de linha no cliente para cada linha retornada pelo db

• Estruturas e objetos internos são reutilizados- Memória- instâncias (exemplo: Geometry)

• Métodos da API que suportam a criação de “recycling cursors” possuem sempre um argumento booleano:- recycling = true cria um “recycling cursor”

O que são Non-Recycling Cursors?

• Um cursor que cria um novo objeto no cliente para cada registro retornado pelo banco de dados

• Estruturas e objetos internos são criados para cada registro - Memory - instâncias (e.g., Geometry)

• Métodos da API que suportam a criação de “recycling cursors” possuem sempre um argumento booleano:- recycling = true cria um “recycling cursor”

Recycling Cursors

•Interfaces com métodos que podem criar “recycling cursors”

•ITable / IFeatureClass-GetRows / GetFeatures-Search-Update

•ISelectionSet / ISelectionSet2-Search-Update

•ITableWrite-UpdateRows

Recycling cursor - Exemplo• Chamadas a NextRow resultam sempre na mesma

instância

Recycling Cursor - Exemplo

Recycling Cursors–Quando utilizar?

• Quando você não precisa de uma referência persistente para um registro

• NÃO passe referências adiante! - Isole o uso das referências em métodos locais onde o

“recycling cursor” foi criado para minimizar o potencial de bugs (em outras palavras: não passe referências para outros métodos pois eles podem decidir mantê-las)

• NUNCA faça uma edição diretamente em um registro reciclado (recycled row)

• Uso apropriado em sessões de edição pode reduzir DRAMATICAMENTE o consumo de recursos

Recycling Cursor Exemplo consumo de recursos

Non-Recycling Cursors–Quando utilizar?

• Quando você precisa de uma referência persistente para um registro ou para algum valor do registro

• Quando você precisa editar o registro ou passar uma referência do mesmo adiante

• Utilizado normalmente para fazer um 'cache' de um conjunto de registros (long lived references)

• Algumas API's requerem um conjunto de registros – nesse caso, esse conjunto deve ser obtido como non-recycled rows

FAQ - Cursores

Quando eu devo liberar a referência de um cursor?

Não mantenha uma referência a um cursor se não for necessário.

Libere ASAP.

FAQ - CursoresSe eu preciso de um cursor em uma sessão de edição

onde eu devo criá-lo?

Dentro do seu bloco de edição(startEditOperation/stopEditOperation)

O importante é NUNCA cruzar fronteiras de operações de edição.

FAQ - Cursores

Devo utilizar um cursor de consulta (Search) para atualizar registros?

Sim. Na verdade, cursores de consulta são a forma recomendada de atualizar registros em sessões de edição.

FAQ - Cursores

Que tipo de cursor eu devo utilizar para alterações?

•ArcMap – possibilidade do cache satisfazer a consulta e nenhuma consulta ao BD ser necessária

• Engine Simple Data- Dentro ES – tira vantagem das atualizações em lote em operações de edição - Outside ES – performance, possibilidade de tratar erros por registro

• Engine Complex Data – Independente. O sistema irá emular uma consulta internamente

Schema Cache

* Um snapshot do schema do geodatabase- Utilizado pelo ArcGIS (abertura de Map Documents, Reconcile)- Requer um um modelo de dados estático- Mudanças no schema não serão refletidas no cache

* Pode melhorar a performance na abertura de datasets reduzindo as consultas ao banco de dados

• Schema Cache API - IWorkspaceFactorySchemaCache

Schema Simplificado – ArcGIS 10

• No ArcGIS 10 o schema do geodatabase foi reconstruído

- Estrutura mais simples (4 tabelas GDB_* ao invés de 35+)- Capacidades de busca otimizadas- Schema aberto (sem serialização binária)- Bem documentado - XML

Schema Simplificado – ArcGIS 10• Acesso mais fácil as informações

• Mais escalável para um numero grande de datasets

• Melhor performance nas consultas ao schema

• Melhor 'fundação' para suportar mais tipos de dataset no futuro

• Suporte a “File Geodatabase API”

• Suporte a “forward compatibility” (a partir do ArcGIS 10 SP2)

Erros mais comuns• Uso incorreto de “recycling cursors”

• Chamadas a FindField em loops

• Utilização de cursor entre operações de edição

• DDL em sessões de edição

• Chamadas a “Store” dentro de eventos disparados por

“store”

• Utilização de GetFeature ao invés de GetFeatures

• Reuso descuidado de variáveis

• Alteração de objetos de schema que não são persistidos

• Inclusões e notificações de “relationship class”

Uso incorreto de “recycling cursors”

Chamadas a FindField em loops

• Utilizar FindField ao invés de posições “hard-coded” é UMA boa pratica mas o uso excessivo pode impactar

performance

Utilização de cursor entre operações de edição

• Isso está documentado como “NÃO FAÇA ISSO!”

• Bloqueado a partir do 10.0

DDL em sessões de edição

• Métodos que podem disparar comandos DDL, como IFeatureWorkspace.CreateTable ou Iclass.AddField devem ser evitados dentro de sessões de edição- Comandos DDL irão efetuar “commit” em qualquer transação corrente, tornando impossível efetuar “rollback” em qualquer edição não desejada se algum erro ocorrer.

- Exemplo: uma aplicação de edição customizada que adiciona um valor a um domínio baseado em um valor informado pelo usuário pode falhar inesperadamente quando da tentativa de “commit” das alterações.

Chamadas a “Store” em eventos disparados por “store”

• Chamar “Store” no mesmo objeto dispara o modelo de eventos, levando a um comportamento inesperado.

- Em alguns casos isso pode resultar em recursão infinita fazendo a aplicação travar. Em outros casos erros podem ser retornados com mensagens que podem ser difíceis de interpretar

Utilização de GetFeature ao invés de GetFeatures

Performance: Toda vez que mais de uma feature for retornada utilizando um objectID conhecido, SEMPRE utilize o método GetFeatures Evite fazer chamadas individuais (GetFeature) se isso for possível

Reuso descuidado de variáveis

Alteração de objetos de schema que não são persistidos

• Em modificações de objetos – e.g., datasets, domains, fields, etc., você deve estar atento ao fato dessas classes serem divididas em duas categorias com os seguintes comportamentos:- Aquelas que serão automaticamente persistidas (“tables”)- Aquelas que podem não ser (fields, domains, indexes)

• Um exemplo clássico são os métodos IClass.AddField() e IFieldsEdit.AddField()- quando o 1o é chamado a API adiciona o campo a tabela no banco de dados- quando o 2o é chamado o campo é adicionado somente na memória. A alteração não é efetuada no banco de dados

Inclusões e notificações de “relationship class”

• Notificações (também conhecida como mensagens) garante o comportamento apropriado em relacionamentos compostos, feature-linked annotation e custom class extensions- Esse comportamento tem um custo - Inclusões e alterações em datasets que disparam notificações são notadamente mais lentos que as mesmas operações em datasets sem notificação

• Essa perda de performance pode ser minimizada se cerificando que todas as classes que serão notificadas estejam abertas antes de qualquer inclusão\alteração

Inclusões e notificações de “relationship class”

Erros mais comuns• Uso incorreto de “recycling cursors”

• Chamadas a FindField em loops

• Utilização de cursor entre operações de edição

• DDL em sessões de edição

• Chamadas a “Store” dentro de eventos disparados por

“store”

• Utilização de GetFeature ao invés de GetFeatures

• Reuso descuidado de variáveis

• Alteração de objetos de schema que não são persistidos

• Inclusões e notificações de “relationship class”

GeoDB Developer Resources

• ESRI Blogs (blogs.esri.com)- Inside the Geodatabase

• Geodatabase“How To” Articles- Developers Guide to the Geodatabase

- Many more articles in Geodatabase SDK

More GeoDB Developer ResourcesEffective Geodatabase Programming – ESRI DevSummit 2012http://video.esri.com/series/87/2012-esri-developer-summit-technical-workshops

Effective Geodatabase Programming – ESRI DevSummit 2011http://proceedings.esri.com/library/userconf/devsummit11/tech/tech_39.htmlhttp://proceedings.esri.com/library/userconf/devsummit11/videos/video64.html

http://proceedings.esri.com/library/userconf/devsummit11/papers/tech/effective_geodatabase_programming.pdf

Common Geodatabase API Programming Mistakes (9.3)http://resources.esri.com/help/9.3/ArcGISEngine/dotnet/09bd8059-f031-4b88-bac8-3b4b73dccb05.htm

Geodatabase API best practices (10)http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000047000000

XML Schema of Geodatabase “White Paper”http://downloads.esri.com/support/whitepapers/ao_/XML_Schema_of_Geodatabase.pdf

Obrigado!

Bruno CaimarImagem Soluções Verticais

bcaimar@img.com.br

Abril/2012