Archive for December 13th, 2007

13
Dec

ADO.NET Data Services Part 2: Service Addressing

In the last two posts, hopefully it became very clear just host flexible ADO.NET Data Services truly are. We now know how to create the actual service (with any type of data store), and setup the necessary access rights. Now it’s time to get into the juicy stuff: querying the service for data.

I previously mentioned that data services give you data retrieval, paging, filtering, and sorting for free. You may have thought “Well that sounds great, but why don’t you show me!”, and that is exactly what I’m going to do.

A data service can be queried from many different environments (as we’ll see in later posts), using numerous different APIs (which we’ll also see in later posts), but at its very core is a REST interface. By that I mean that the data service itself is 100% exposed through URLs. There is no need for a proxy, no RPC calls, no SOAP messaging serialization. The REST model has gained a lot of popularity over the last few years and rightfully so. It’s very clean, easy, and explicit.

Let’s go back to the service we created in part 1. Hit F5 and view our service:

astoria31.JPG

Once again, we see our service, and the CellPhone entity that we explicitly set read-only rights for. Remember also that it is displaying “CellPhones” not “CellPhone” because “CellPhones” is the name of the IQueryable<T> property that exposes the CellPhone entity. You could obviously rename the property to whatever you wanted, for display in the service.

Another point of interest is that the default format used by the data service is APP, or Atom Publishing Protocol (aka AtomPub). This is not the only format you can receive from your data service, as we’ll see in later posts.

Alright, back to business. If I were to look at the URL in my web browser, currently I would see http://localhost:64701/Services/CellPhoneShackService.svc. That svc file is what represents my data service, and making an HTTP request to it garners the above AtomPub response. So because data services are RESTful, we know that all we have to do to traverse/work with the data is append on to the base URL. Reason would lead you to believe that appending the name of the data collection you want to retrieve would yield some results, which is exactly true. If I append /CellPhones to my above URL, and hit enter, I get the following:

astoria22.JPG

There were a lot more <entry> elements in the list, but I truncated is fore brevity. As you can see, just by simply appending the data collection name to the end of the service URL, I traversed into the cell phone entity. Pretty sweet eh? I sure think so.

Notice the <id> element in the above <entry>. It contains a URL that represents the access point for retrieving that specific entity instance (in this case the iPhone). The only thing new here to the syntax we’re currently using is the “(’iPhone’)” construct, which is how you address an entity by its key value (in this case the model name). Now can you see the reason why we had to append the WebDataKey attribute to the ModelName property? The data service has to know which property you’re referring to when you request a specific entity by key. Notice also that “iPhone” is quoted, because the entity’s key value is a string. If the key value was an integer, it could expressed as just CellPhones(2).

If I was to append “(’iPhone’)” to my current URL, I would receive just the iPhone data and nothing more. What I think is great about the data service embedding the entity’s URL in the <id> element is that you can imagine how easily you could traverse the data source programmatically, lending further to the flexibility of using data services.

Ok, great, now I know how to query an entire data collection (/CellPhones), as well as a specific entity (/CellPhones(’iPhone’)), but what if I just want to grab a single property value out of an entity? For instance, I want to know what the price of the iPhone is. All I have to do is append the name of the property to the end of the URL, like so: /CellPhones(’iPhone’)/Price. That would return to me the following:

astoria23.JPG

Pretty sweet right? Indeed.

Since we’re working with a scalar value (a simple double in this case), what if I wanted just the property’s value, without the extra XML surrounding it? The AtomPub content is certainly valuable and necessary for working with the service in a standard way, but it seems like a waste of bandwidth to have the service send back the entire <Price> element, and all its namespaces, when all we want is the price. Luckily I could modify my above query to /CellPhones(’iPhone’)/Price/$value, which would return to me just the text “399″, without any extra fluff. The $value modifier is referred to as the dereference operator, because you’re asking for just the raw data of the requested property. This operator works solely on scalar properties, and is appended to the property, as if you’re traversing further into it. That means I couldn’t do /CellPhones/$value, or /CellPhones(’iPhone’)/$value, because those are retrieving a collection of entities, and a single entity, respectively. But /CellPhones(’iPhone’)/Megapixels/$value would work just fine, because Megapixels is a scalar property on the CellPhone entity.

Currently, the CellPhone entity doesn’t have any relationships as far as our data service is concerned. The reason for that is because we haven’t “turned on” access for either the Manufacturer or Carrier entities, so the data service doesn’t display the relationships on the CellPhone entity for either of those two (which is a really nice security feature). If I go back to my service and modify the access rights like so:

astoria24.JPG

And then request the iPhone again like so: /CellPhones(’iPhone’), we’ll now see two new elements appear in our CellPhone entry:

astoria25.JPG

In addition to our list of scalar properties, we now have two <link> elements, that point at other entities that the iPhone relates to, namely its carrier and manufacturer. Notice the URL in the <link> element’s href attribute, it simply points at the Carrier and Manufacturer property of the iPhone entity. What’s neat about that is that it shows that the data service allows you to traverse entity properties the same way regardless if they’re scalar or referential. Requesting the following URL would retreive the carrier instance that provides service for the iPhone: /CellPhones(’iPhone’)/Carrier.

astoria26.JPG

Here we see the AT&T carrier, which is what we’d expect to receive (since the iPhone is stupidly exclusive to AT&T). Notice that the AT&T carrier also has a relationship property back to all of its cell phone instances. You can begin to see how creative you can get with your queries.

The data service is simply exposing whatever domain model you’ve created, so you can comfortably query your service using the same semantics and structure you’ve setup. If you didn’t want a relationship from the Carrier entity to its respective CellPhone entities, you could just remove it from your model. The data service isn’t creating anything on top of your model you don’t want.

We’ve covered addressing our service, retrieving collections of data, and traversing our data collections through the use of keys, scalar properties, and relationships. In the next post we’ll cover how to use query parameters to filter, page, and sort the returned data.




December 2007
S M T W T F S
« Nov   Jan »
 1
2345678
9101112131415
16171819202122
23242526272829
3031  

Categories