ADO.NET Data Services (aka “Project Astoria”) has Released! Today marks the official RTM of Visual Studio 2008 SP1 and the .NET Framework 3.5 SP1, and we are thrilled to announce the official RTM of the ADO.NET Entity Framework and ADO.NET Data Services.
You can find more information and download SP1 at http://msdn.microsoft.com/data .
The remainder of this post will cover the changes and additions to the ADO.NET Data Services Framework since the Beta. This post will just give a brief summary of each and we’ll follow up with more targeted posts overtime to get a bit deeper into the details.
Changes \ Enhancements:
Tweaks to the ATOM payload: We've made a few tweaks to the payload format based on feedback from the ATOM community and to enable us to land on a simpler overall set of semantics for CRUD operations across resources and links between resources. One of the most significant improvements is that links/associations are now directly addressable so it’s clear when you are working with an link\association vs. working with a resource\entity. Using the Northwind database schema as an example, to address the set of links between a Customer and their Orders, the following URI is available: http://myserver/myservice/Customers(‘ALFKI’)/$links/Orders. This new $links segment allows associations to be addressed and manipulated directly. We’ll follow up with additional examples and whitepapers showing the details of this syntax in future posts.
A handful of bug fixes J.
Tweaks to our optimistic concurrency support: We added support for the ‘*’ character to be used with conditional HTTP requests. We also changed to use weak Etags instead of strong Etag values to better align with the HTTP spec and its current set of ammendums.
Tweaks to the .NET client library: The response object from the SaveChanges(…) method has changed to make it easier to get at all aspects (headers, etc) of each section of the data service response. The most significant difference is the HasErrors properties from the *Response classes are removed. Instead, if one or more errors occur during the processing of a call to SaveChanges(…), the method will throw an exception. The exception contains a property to access the full response to determine which operations succeeded and which failed (assuming SaveChangesOptions.Batch was not used which provides “all or nothing” semantics).
Additional configuration of system limits: A number of system limits are now publically exposed via the IDataServiceConfiguration class enabling a data service author more control over the requests their service is willing to accept and process
Additional plug-in points in the processing pipeline: Just after URI syntactic analysis is complete, we have added a call out in the processing pipeline called OnStartProcessingRequest. This call out enables custom service code to run at a very early point in the request processing pipeline.
“Add Service Reference” support for client proxy generation: The command line tool to generate client side types for a data service (datasvcutil.exe) can still be found in the \Windows\Microsoft.Net\Framework\V3.5 directory; however, we are pleased to announce the “Add Service Reference” feature in Visual Studio now supports accepting ADO.NET Data Service URIs.
Service versioning support: Data services now directly support a lightweight versioning scheme enabled via HTTP headers. The scheme has been designed with the goal of enabling existing clients to work with new service versions (and vice versa) when safely possible. The goal was taken as it seems for internet facing data services one needs to assume clients and services will rev at different speeds.
Control error messages: Data service authors can now easily control all error messages and associated status codes returned to a client as a result of an error while processing a data service request. The HandleException method on the DataService class is now called for any exception that occurs while processing a request. A data service author can then map any downstream exception to sections of the error message structure used by data services.
We want to work on a round of blog posts to address a few of the common questions folks have when using data services. We’ve got a number in mind already, but if you have a question/comment that would make a good blog post let us know. We likely won’t be able to answer each with a full blog post, but we’ll try to address the common ones.
-Mike Flasko Program Manager, ADO.NET Data Services
Rory: the best place for Astoria discussion is the Astoria forum:
It's amazing how much information is there in our email archives. Now that we've shipped the thing, I
I'm also distraught about the lack of efficient results count. My main ajax control (a grid) utilizes on-demand data fetching as the grid is scrolled. I need an accurate count to be able to allow skipping through records by dragging the scroll bar and indicating which records are visible as a range - along with using the count value with the scroll bars themselves to size the grab region.
Retrieving the count of records in an efficient manner is an absolute necessity for modern AJAX.
Yes, I agree that not having count is painful. Hopefully we'll be able to address that soon.
That said, I've seen various AJAX clients that do without it for various reasons. For example, the Yahoo mail interface dynamically adjusts the scrollbar and content in general as you scroll down and they find more about the items available.
As a bit of background: for the cases where data is in a relational database, in general obtaining the row count is a quite expensive operation (often it involves counting rows in the most compact index/heap available). There are shortcuts sometimes, but they introduce a non-uniform way of finding out the count.
Also, naturally, the count is pretty much always innacurate. The moment the value left the server, it may already have chanced undernead; also, page counts can change from page to page. So for various reasons certain level of innacuracy needs to be tolerated by the app.
Perhaps I've put too much emphasis on the accuracy side of things. You can see what I'm attempting to do here: http://www.siteartwork.de/livegrid_demo/
If it's off by 2 out of 1,000 due to new inserts - no big deal. But I do need to know whether there's 100 or 5,000 results. If it takes 2 seconds of extra processing to determine that there's 5000 results - that's no big deal as I'm not going to ever have to get that count again for the view. This same requirement applies to many other things I will need to do with my project - letting the user know they're on page 1 of 20 in a particular category, that their search for some broad term has returned an enormous amount of results and that they should refine things futher, etc.
From what I've been reading lately, I'm not sure that it's even possible to count the entities returned server side while using a filter or other logic via the URI. Is there *any* way to determine the number of results being returned through a URI such as
/Orders?$filter=ShipCountry eq 'France'
that can be self-contained in the data layer (ie. no counting rows client side)? The answer to that question is the maker/breaker.
I appreciate you taking your time to reply.
For the case where you're using a database as a backend (e.g. it's not your LINQ implementation), which is the most common case, I don't think there is a way of doing this short of looking at the filter expression yourself, which I would strongly encourage not to.
I checked out the grid sample and the grid looks really, really nice. Impressive job.
For something like a data service, you'd have to dynamically fix up the scrollbar as you find out that more rows are available, or introduce a next/prev kind of UI (which I understand that doesn't fit well in the grid as it is today).
I'll keep this in the back of my mind. If I come up with some approach to do this I'll post it somewhere.
I am truly flabbergasted that there is no way to determine the number of results returned. Data Services seems kind of pointless to me, if this simple requirement can't be fulfilled.
If we DID provide a next/previous page we wouldn't even know when to disable the "NEXT" button unless the client-side count happened to be less than our $top value! This is so silly! Why even provide paging if you can't tell what page you're on!? Why waste your time offering paging functions if you didn't plan to let us know when we're on the last page? This is so absolutely silly. Data Services paging belongs on the from page of The Daily WTF - really.
.NET Framework 3.5 SP1 and Visual Studio 2008 SP1 Released
I have to agree with Nick. Data Services without paging is silly. The product is not feature complete until this is added.
@Robert: we heard that loud and clear from all of you guys, so we're working to add that feature for the next release. We should have the feature built into the first public beta/ctp/whatever release that we ship.
Standard disclaimer applies: there is never a guarantee about features for unreleased products until they hit RTM.
Thanks Pablo, good to hear --
For now, I'm using a WebGet method to retrieve the count and I've learned that field names in the string predicate must specify the "it" namespace ... such as "it.Category == \"Overstock\""
Can you explain this? I can't find any documentation on "it"
public int CountOrders(string prediate)
// Note: field names in the prediate must be prefixed with "it."