Upload
bruno-caimar
View
281
Download
21
Embed Size (px)
Citation preview
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
Abril/2012