Guia de protocolo OData

Guia de protocolo OData

1. Introdução

Neste tutorial, vamos explorarOData, a standard protocol that allows easy access to data sets using a RESTFul API.

2. O que é OData?

OData é um padrão OASIS e ISO / IEC para acessar dados usando uma API RESTful. Como tal, permite que um consumidor descubra e navegue pelos conjuntos de dados usando chamadas HTTP padrão.

For instance, we can access one of the publicly available OData services with a simple curl one-liner:

curl -s https://services.odata.org/V2/Northwind/Northwind.svc/Regions


    Regions
    https://services.odata.org/V2/Northwind/Northwind.svc/Regions
... rest of xml response omitted

No momento da redação deste documento, o protocolo OData está na sua quarta versão - 4,01 para ser mais preciso. O OData V4 atingiu o nível padrão OASIS em 2014, mas tem um histórico mais longo. Podemos rastrear suas raízes em um projeto da Microsoft chamado Astoria, quewas renamed to ADO.Net Data Services in 2007. Ooriginal blog entry anunciando este projeto ainda está disponível no blog OData da Microsoft.

Having a standards-based protocol to access data set brings some benefits over standard APIs such as JDBC or ODBC. Como consumidor de nível de usuário final, podemos usar ferramentas populares como o Excel para recuperar dados de qualquer provedor compatível. A programação também é facilitada por um grande número de bibliotecas de clientes REST disponíveis.

Como fornecedores, adotar OData também traz benefícios: uma vez que criamos um serviço compatível, podemos nos concentrar em fornecer conjuntos de dados valiosos, que os usuários finais podem consumir usando as ferramentas de sua escolha. Por ser um protocolo baseado em HTTP, também podemos aproveitar aspectos como mecanismos de segurança, monitoramento e registro.

Essas características tornaram o OData uma escolha popular por agências governamentais na implementação de serviços públicos de dados, como podemos verificar portaking a look at this directory.

3. Conceitos OData

No núcleo do protocolo OData está o conceito de um Modelo de Dados de Entidade - ou EDM, para abreviar. O EDM descreve os dados expostos por um provedor OData por meio de um documento de metadados que contém várias meta-entidades:

  • Tipo de entidade e suas propriedades (por exemplo, Person,Customer,Order, etc) e chaves

  • Relações entre entidades

  • Tipos complexos usados ​​para descrever tipos estruturados incorporados em entidades (digamos, um tipo de endereço que faz parte de um tipoCustomer)

  • Conjuntos de entidades, que agregam entidades de um determinado tipo

A especificação exige que este documento de metadados esteja disponível no local padrão$metadata no URL raiz usado para acessar o serviço. Por exemplo, se tivermos um serviço OData disponível emhttp://example.org/odata.svc/, então seu documento de metadados estará disponível emhttp://example.org/odata.svc/$metadata.

O documento retornado contém um monte de XML que descreve os esquemas suportados por este servidor:



    
    ... schema elements omitted
    

Vamos dividir este documento em suas seções principais.

O elemento de nível superior,<edmx:Edmx> can tem apenas um filho, o elemento<edmx:DataServices>. * * O importante a ser observado aqui é o URI do namespace, pois ele nos permite identificar qual versão OData do servidor usa. Nesse caso, o namespace indica que temos um servidor OData V2, que usa identificadores da Microsoft.

Um elementoDataServices pode ter uma ou mais seleçõesSchema , cada uma descrevendo um conjunto de dados disponível. Como uma descrição completa dos elementos disponíveis em aSchema está além do escopo deste artigo, vamos nos concentrar nos mais importantes:EntityTypes, Associations,eEntitySets.

3.1. ElementoEntityType

Este elemento define as propriedades disponíveis de uma determinada entidade, incluindo sua chave primária. Ele também pode conter informações sobre relacionamentos com outros tipos de esquema e, olhando para um exemplo - aCarMaker –, poderemos ver que não é muito diferente das descrições encontradas em outras tecnologias ORM, como JPA:


    
        
    
    
    
    

Aqui, nossoCarMaker tem apenas duas propriedades -Id areiaName - e uma associação a outroEntityType. O subelementoKey sdefine a chave primária da entidade como suaId property, e cada elementoProperty contém dados sobre a propriedade de uma entidade, como seu nome, tipo ou nulidade.

UmNavigationProperty é um tipo especial de propriedade que descreve um “ponto de acesso” para uma entidade relacionada.

3.2. Association Element

Uma seleçãoAssociation descreve uma associação entre duas entidades, que inclui a multiplicidade em cada extremidade e, opcionalmente, uma restrição de integridade referencial:


    
    
    
        
            
        
        
            
        
    

Aqui, o elementoAssociation define uma relação um-para-muitos entre as entidadesCarModeleCarMaker, onde a primeira atua como a parte dependente.

3.3. ElementoEntitySet

O conceito de esquema final que vamos explorar é o elementoEntitySet, que representa uma coleção de entidades de um determinado tipo. Embora seja fácil considerá-los análogos a uma mesa - e em muitos casos, eles são apenas isso - uma analogia melhor é a de uma visualização. A razão para isso é quewe can have multiple EntitySet elements for the same EntityType, cada um representando um subconjunto diferente dos dados disponíveis.

O elementoEntityContainer, que é um elemento de esquema de nível superior, agrupa todos osEntitySets disponíveis:


    
    

Em nosso exemplo simples, temos apenas doisEntitySets, mas também podemos adicionar visualizações adicionais, comoForeignCarMakers ouHistoricCarMakers.

4. URLs e métodos OData

Para acessar os dados expostos por um serviço OData, usamos os verbos HTTP regulares:

  • GET retorna uma ou mais entidades

  • POST adiciona uma nova entidade a umEntity Set existente

  • PUT substitui uma determinada entidade

  • PATCH substitui propriedades específicas de uma determinada entidade

  • DELETE remove uma determinada entidade

Todas essas operações requerem um caminho de recurso para agir. O caminho do recurso pode definir um conjunto de entidades, uma entidade ou mesmo uma propriedade dentro de uma entidade.

Vamos dar uma olhada em um exemplo de URL usado para acessar nosso serviço OData anterior:

http://example.org/odata/CarMakers

A primeira parte desta URL, começando com o protocolo até o segmento de caminhoodata/, é conhecida comoservice root URLe é a mesma para todos os caminhos de recursos deste serviço. Since the service root is always the same, we’ll replace it in the following URL samples by an ellipsis (“…”).

CarMakers, neste caso, refere-se a um dosEntitySets declarados nos metadados do serviço. Podemos usar um navegador comum para acessar este URL, que deve retornar um documento contendo todas as entidades existentes desse tipo:



    http://localhost:8080/odata/CarMakers
    CarMakers
    2019-04-06T17:51:33.588-03:00
    
        
    
    
    
      http://localhost:8080/odata/CarMakers(1L)
      CarMakers
      2019-04-06T17:51:33.589-03:00
      
      
      
        
            
                1
                Special Motors
            
        
    
  ... other entries omitted

O documento retornado contém um elementoentry para cada instânciaCarMaker.

Vamos dar uma olhada mais de perto nas informações que temos disponíveis para nós:

  • id: um link para esta entidade específica

  • title/author/updated: metadados sobre esta entrada

  • Elementoslink: links usados ​​para apontar para um recurso usado para editar a entidade (rel=”edit”) ou para entidades relacionadas. Nesse caso, temos um link que nos leva ao conjunto de entidadesCarModel associadas a esseCarMaker específico.

  • content: valores de propriedade da entidadeCarModel

Um ponto importante a ser observado aqui é o uso do par de valores-chave para identificar uma entidade específica dentro de um conjunto de entidades. Em nosso exemplo, a chave é numérica, então um caminho de recurso comoCarMaker(1L) refere-se à entidade com um valor de chave primária igual a 1 - o “L” aqui apenas denota um valorlong e poderia ser omitido.

5. Opções de consulta

Podemos passar opções de consulta para um URL de recurso para modificar vários aspectos dos dados retornados, como limitar o tamanho do conjunto retornado ou sua ordem. A especificação OData define um rico conjunto de opções, mas aqui vamos nos concentrar nas mais comuns.

Como regra geral, as opções de consulta podem ser combinadas entre si, permitindo que os clientes implementem facilmente funcionalidades comuns, como paginação, filtragem e listas de resultados de pedidos.

5.1. $top e$skip

Podemosnavigate through a large dataset using the $top an $skip query options:

.../CarMakers?$top=10&$skip=10

$top diz ao serviço que queremos apenas os primeiros 10 registros do conjunto de entidadesCarMakers. Um$skip, que é aplicado antes de$top, diz ao servidor para pular os primeiros 10 registros.

Geralmente é útil saber o tamanho de um determinadoEntity Set e, para esse propósito, podemos usar o sub-recurso$count:

.../CarMakers/$count

Este recurso produz um documentotext/plain contendo o tamanho do conjunto correspondente. Aqui, devemos prestar atenção à versão OData específica suportada por um provedor. Enquanto OData V2 oferece suporte a$count como um sub-recurso de uma coleção, V4 permite que ele seja usado como um parâmetro de consulta. Nesse caso,$count é um booleano, portanto, precisamos alterar o URL de acordo:

.../CarMakers?$count=true

5.2. $filter

Usamos a opção de consulta$filter paralimit the returned entities from a given Entity Set para aqueles que correspondem aos critérios fornecidos. O valor de$filter é uma expressão lógica que oferece suporte a operadores básicos, agrupamento e várias funções úteis. Por exemplo, vamos construir uma consulta que retorna todas as instâncias deCarMaker onde seu atributoName começa com a letra 'B':

.../CarMakers?$filter=startswith(Name,'B')

Agora, vamos combinar alguns operadores lógicos para pesquisarCarModels para um determinadoYeareMaker:

.../CarModels?$filter=Year eq 2008 and CarMakerDetails/Name eq 'BWM'

Aqui, usamos o operador de igualdadeeq para especificar valores para as propriedades. Também podemos ver como usar propriedades de uma entidade relacionada na expressão.

5.3. $expand

By default, an OData query does not return data for related entities, que geralmente está OK. Podemos usar a opção de consulta$expand para solicitar que os dados de uma determinada entidade relacionada sejam incluídos em linha com o conteúdo principal.

Usando nosso domínio de amostra, vamos construir um URL que retorna dados de um determinado modeloand seu criador, evitando assim uma viagem de ida e volta adicional para o servidor:

.../CarModels(1L)?$expand=CarMakerDetails

O documento retornado agora inclui os dadosCarMaker como parte da entidade relacionada:



    http://example.org/odata/CarModels(1L)
    CarModels
    2019-04-07T11:33:38.467-03:00
    
    
    
        
            
                http://example.org/odata/CarMakers(1L)
                CarMakers
                2019-04-07T11:33:38.492-03:00
                
                
                
                
                    
                        1
                        Special Motors
                    
                
            
        
    
    
        
            1
            1
            Muze
            SM001
            2018
        
    

5.4. $select

Usamos a opção de consulta $ select para informar o serviço OData que ele deve retornar apenas os valores para as propriedades especificadas. Isso é útil em cenários em que nossas entidades têm um grande número de propriedades, mas estamos interessados ​​apenas em algumas delas.

Vamos usar esta opção em uma consulta que retorna apenas as propriedadesNameeSku :

.../CarModels(1L)?$select=Name,Sku

O documento resultante agora possui apenas as propriedades solicitadas:

... xml omitted
    
        
            Muze
            SM001
        
    
... xml omitted

Também podemos ver que mesmo entidades relacionadas foram omitidas. Para incluí-los, precisaríamos incluir o nome da relação na opção$select.

5.5. $orderBy

A opção$orderBy funciona muito bem como sua contraparte SQL. Usamos para especificarthe order in which we want the server to return a given set of entities. Em sua forma mais simples, seu valor é apenas uma lista de nomes de propriedades da entidade selecionada, informando opcionalmente a direção do pedido:

.../CarModels?$orderBy=Name asc,Sku desc

Esta consulta resultará em uma lista deCarModels ordenada por seus nomes e SKUs, nas direções crescente e decrescente, respectivamente.

Um detalhe importante aqui é o caso usado com a parte de direção de uma determinada propriedade: enquanto a especificação determina que o servidor deve suportar qualquer combinação de letras maiúsculas e minúsculas para as palavras-chaveascedesc, tambémmandates that client use only lowercase.

5.6. $format

Esta opção define o formato de representação de dados que o servidor deve usar, que tem precedência sobre qualquer cabeçalho de negociação de conteúdo HTTP, comoAccept. Seu valor deve ser um tipo MIME completo ou um formato abreviado específico do formato.

Por exemplo,we can use json as an abbreviation for application/json:

.../CarModels?$format=json

Este URL instrui nosso serviço a retornar dados usando o formato JSON, em vez de XML, como vimos antes. Quando esta opção não estiver presente, o servidor usará o valor do cabeçalhoAccept, se houver. Quando nenhum deles estiver disponível, o servidor poderá escolher qualquer representação - geralmente XML ou JSON.

Com relação ao JSON especificamente, ele é fundamentalmente sem esquema. No entanto, OData 4.01 definea JSON schema for metadata endpoints também. Isso significa que agora podemos escrever clientes que podem se livrar totalmente do processamento XML, se optarem por fazê-lo.

6. Conclusão

Nesta breve introdução ao OData, cobrimos sua semântica básica e como realizar uma navegação simples no conjunto de dados. Nosso artigo de acompanhamento continuará de onde saímos e iremos direto para a biblioteca do Olingo. Veremos então como implementar serviços de amostra usando esta biblioteca.

Exemplos de código, como sempre, estão disponíveisover on GitHub.