Recuperando e Atualizando Dados com o REST

O protocolo OData requer que todas as entidades possam ser endereçadas por sua forma canônica. Isso significa que cada entidade deve incluir a chave da entidade raiz particionada, a raiz do esquema.

A seguir está um exemplo de como utilizar a associação de uma entidade raiz para endereçar um filho em:
/Customer('ACME')/order(100)

No WCF Data Services, a entidade-filha deve ser diretamente endereçável, o que significa que a chave na raiz do esquema deve fazer parte da chave da filha: /Order(customer_customerId='ACME', orderId=100). Isso é conseguido por meio da criação de uma associação com a entidade raiz, em que a associação um-para-um ou muitos-para-um com a entidade raiz também é identificada como uma chave. Quando entidades são incluídas como parte da chave, os atributos da entidade pai são expostos como propriedades-chave.

Figura 1. Diagrama do Esquema de Entidade Cliente e Ordem
Diagrama do esquema da entidade Customer e Order

O diagrama do esquema de entidade Cliente/Ordem ilustra como cada entidade é particionada usando o Cliente. A entidade Order inclui Customer como parte de sua chave e é, portanto, diretamente acessível. O serviço de dados REST expõe todas as associações chave como propriedades individuais: Order tem customer_customerId e OrderDetail tem order_customer_customerId e order_orderId.

Utilizando a API EntityManager, é possível localizar Order utilizando o id de Customer e Order:

transaction.begin();
// Look-up the Order using the Customer.  We only include the Id
// in the Customer class when building the OrderId key instance.
Order order = (Order) em.find(Order.class, 
    new OrderId(100, new Customer('ACME')));
...
transaction.commit();
Ao utilizar o serviço de dados REST, Order pode ser recuperada com qualquer uma das seguintes URLs:
  • /Order(orderId=100, customer_customerId='ACME')
  • /Customer('ACME')/orders?$filter=orderId eq 100

A chave do cliente é endereçada utilizando o nome do atributo da entidade Customer, um caractere sublinhado e o nome do atributo do id de Customer: customer_customerId.

Uma entidade também pode incluir uma entidade não raiz como parte de sua chave se todos os ancestrais para a entidade não raiz tiverem associações de chave com a raiz. Neste exemplo, OrderDetail tem uma associação de chave com Order, e Order tem uma associação de chave com a entidade Customer raiz. Utilizando a API EntityManager:

transaction.begin();
// Construct an OrderDetailId key instance.  It includes
// The Order and Customer with only the keys set. 
Customer customerACME = new Customer("ACME");
Order order100 = new Order(100, customerACME);
OrderDetailId orderDetailKey = 
    new OrderDetailId(order100, "COMP");
OrderDetail orderDetail = (OrderDetail) 
    em.find(OrderDetail.class, orderDetailKey); 
...

O serviço de dados REST permite endereçar OrderDetail diretamente:

/OrderDetail(productId=500,
order_customer_customerId='ACME', order_orderId =100)

A associação da entidade OrderDetail com a entidade Product foi quebrada para permitir o particionamento de Orders e Product Inventory independentemente. A entidade OrderDetail armazena o ID do produto e categoria de um relacionamento sólido. Ao desacoplar os dois esquemas de entidade, apenas uma partição é acessada por vez.

O esquema Categoria e Produto ilustrado no diagrama mostra que a entidade-raiz é Categoria e cada Produto tem uma associação com uma entidade Categoria. A entidade Category está incluída na identidade de Product. O serviço de dados REST expõe uma propriedade-chave: category_categoryId, que permite o endereçamento direto de Product.

Como Categoria é a entidade-raiz, em um ambiente particionado, a Categoria deve ser conhecida para localizar o Produto. Utilizando a API EntityManager, a transação deve ser retida na entidade Category antes de localizar Product.

Utilizando a API EntityManager:

transaction.begin();
// Create the Category root entity with only the key.  This
// allows us to construct a ProductId without needing to find
// The Category first.  The transaction is now pinned to the 
// partition where Category "COMP" is stored.
Category cat = new Category("COMP");
Product product = (Product) em.find(Product.class, 
    new ProductId(500, cat)); 
...

O serviço de dados REST permite endereçar Product diretamente:

/Product(productId=500,
category_categoryId='COMP')