REST を使用したデータの取得および更新

OData プロトコルは、すべてのエンティティーが正規化形式でアドレス指定できることを要求します。 つまり、各エンティティーは区画に分割されたルート・エンティティー、スキーマ・ルートのキーを含んでいなければなりません。

以下は、子エンティティーをアドレス指定するためのルート・エンティティーからのアソシエーションの使用方法の例です。
/Customer('ACME')/order(100)

WCF Data Services では、子エンティティーは直接アドレス可能でなければなりません。つまり、スキーマ・ルートのキーは、次のように子のキーの一部でなければなりません。/Order(customer_customerId='ACME', orderId=100) これは、ルート・エンティティーへのアソシエーションの作成により実現され、ルート・エンティティーへの 1 対 1 または多対 1 のアソシエーションもキーとして識別されます。 エンティティーがキーの一部として組み込まれる場合、親エンティティーの属性はキー・プロパティーとして公開されます。

図 1. Customer および Order エンティティーのスキーマ図
Customer および Order エンティティーのスキーマ図

Customer/Order エンティティーのスキーマ図で、どのように各エンティティーが Customer を使用して区画に分割されているかを示しています。Order エンティティーにはキーの一部として Customer が組み込まれるため、直接アクセスすることができます。 REST データ・サービスは、すべてのキー・アソシエーションを個別のプロパティーとして公開します。Order には customer_customerId があり、OrderDetail には order_customer_customerId および order_orderId があります。

EntityManager API を使用すると、Customer とオーダー ID を使用して 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();
REST データ・サービスを使用する場合、どちらかの URL を使用して Order を取得することができます。
  • /Order(orderId=100, customer_customerId='ACME')
  • /Customer('ACME')/orders?$filter=orderId eq 100

カスタマー・キーは Customer エンティティーの属性名 (下線文字とカスタマー ID の属性名 customer_customerId) を使用してアドレス指定されています。

エンティティーには、非ルート・エンティティーのすべての上位エンティティーがルートへのキー・アソシエーションを持つ場合は、キーの一部として非ルート・エンティティーを組み込むこともできます。 この例では、OrderDetail には Order へのキー・アソシエーションがあり、Order にはルートの Customer エンティティーへのキー・アソシエーションがあります。 EntityManager API の使用は、次のとおりです。

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); 
...

REST データ・サービスは、OrderDetail に直接アドレスを指定することができます。

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

OrderDetail エンティティーから Product エンティティーへのアソシエーションは分割され、Orders および Product インベントリーを個別に区画に分割することができます。 OrderDetail エンティティーは、強いリレーションシップの代わりにカテゴリーと製品 ID を保管します。 2 つのエンティティー・スキーマを切り離すと、一度に 1 つの区画だけがアクセスされます。

Category および Product スキーマは、図で示すように、ルート・エンティティーが Category で、各 Product には Category エンティティーへのアソシエーションがあることを表しています。Category エンティティーは Product ID に組み込まれています。 REST データ・サービスは、キー・プロパティーを公開します。category_categoryId で Product に直接アドレスを指定できます。

Category はルート・エンティティーなので、区画に分割された環境で Product を検索するには、Category が認識されている必要があります。EntityManager API を使用すると、Product の検索前にトランザクションは Category エンティティーに pinned されなければなりません。

EntityManager API の使用は、次のとおりです。

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)); 
...

REST データ・サービスは、Product に直接アドレスを指定することができます。

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