Linq to REST

Late Sunday night we released the first public preview of ASP.NET 3.5 Extensions.  For information on the release, see ScottGu’s announcement.

As part of that preview, we released the first CTP of the production version of Project Astoria.  For details, see public release announcement by Mike Flasko on the Astoria Team Blog.

Astoria actually has been given its official Microsoft name:  ADO.NET Data Services.  So, in this post I will use the name Astoria and Data Services interchangeably.

For a complete overview of Astoria check out the information available on Microsoft Live Labs.

For the next few weeks, I will be writing a series of blog posts to demonstrate what I think is one of the most compelling features in Astoria, namely remote execution of Linq queries via the RESTFUL API exposed by Astoria Data Services.

For these posts, I will be covering:

1)  How to set up an Astoria Data Service which can be used for remote execution of Linq queries.

2)  Dive deep into the Astoria Client API’s Linq support including a detailed description of how Linq queries are translated to URIs.

3)  How to make the Astoria Data Service updateable so the results of the Linq queries can be remotely modified and persisted.

So the goal of this initial post is to set up an Astoria Data Service over a Linq to Sql DataContext source and remotely execute a Linq query via the Astoria client library over HTTP.

(The following steps assume Visual Studio 2008 and ASP.NET 3.5 Extensions has been installed.  Also, this demo assumes access to the Sql Server sample Northwind database).

First, Create a standard ASP.NET Web Application:


Next, add an ADO.NET Data Service called Northwind.svc to the project via the Add New Item option:


Next, add a new set of Linq to Sql via the designer called Northwind.dbml.


From my Data Connections in the Server Explorer, I add the Categories, Products, and Supplier tables to Northwind.dbml from the Northwind database


Because the keys for the new types follow the Astoria convention of being named [EntityName]Id, I don’t have to do anything further.  The Linq to Sql data classes and the strongly typed DataContext (NorthwindDataContext) is totally useable with Astoria without any modifications.

Next, I want to wire up my Astoria Data Service to use NorthwindDataContext as the data source.  To do this, go back to the Northwind.svc.cs file that was created when the Astoria Data Service was added to the project.  Look for the TODO’s in the Northwind class:

    public class Northwind : WebDataService< /* TODO: put your data source class name here */ >
        // This method is called once during service initialization to allow
        // service-specific policies to be set
        public static void InitializeService(IWebDataServiceConfiguration config)
            // TODO: set rules to indicate which entity sets and service operations are
            // visible, updatable, etc.
            // (for testing purposes use "*" to indicate all entity sets/service
            // operations, but that option should NOT be used in production systems)

            // Example for entity sets (this example uses "AllRead" which allows reads but not writes)
            // config.SetResourceContainerAccessRule("MyEntityset", ResourceContainerRights.AllRead);

            // Example for service operations
            // config.SetServiceOperationAccessRule("MyServiceOperation", ServiceOperationRights.All);

        // Query interceptors, change interceptors and service operations go here

First, put the name of the DataContext in as the generic parameter for the Northwind class.

Next. add the following line to the InitializeService method:

config.SetResourceContainerAccessRule("*", ResourceContainerRights.AllRead);

By default, Astoria turns off all access to the data source.  By adding this line, I am giving read access to all public IQueryable<T> entry points on the DataContext. 

Note, the wildcard option (*) should only be used for testing purposes.  For actual application development, please explicitly grant access to each IQueryable<T> entry point by via the property name.

Now build the application and press F5 to fire it up.  If everything went ok, you should get back the following Atom service definition when you access the URI http://localhost:18752/Northwind.svc/ (I am using port 18752 with Cassini for debugging).


  <service xml:base="http://localhost:18752/Northwind.svc/" xmlns:atom="" xmlns:app="" xmlns="">
       <collection href="Categories">
       <collection href="Products">
       <collection href="Suppliers">


Now, try a few URIs to make sure everything it working:

(Note, Internet Explorer by default renders ATOM in a friendly format that makes Astoria feeds unreadable.  To fix this, turn off IE feed viewing by turning off the option :  Tools -> Internet Options -> Content ->  Feeds (settings) -> Turn on feed viewing)

http://localhost:18752/Northwind.svc/Products – gets all the Products

http://localhost:18752/Northwind.svc/Products(2) – gets the Product with ProductId == 2

http://localhost:18752/Northwind.svc/Products?$filter=UnitsInStock gt 100 – gets all the Products where UnitsInStock is greater than 100

http://localhost:18752/Northwind.svc/Products?$orderby=ProductName&$top=10 – orders the Products by ProductName and gets the first 10.


For more information about Astoria’s URI Addressing Scheme see here.

Now, lets get a sample Linq query working.

First, add another project to the solution.  In this case, a simple console Application will work:


In this project, add a reference to the Astoria client library assembly called Microsoft.Data.WebClient.dll. It should be in your /Program Files/Reference Assemblies/Microsoft/Framework/ASP.NET 3.5 Extensions directory.

Now add make sure the namespace Microsoft.Data.WebClient is in scope, and add the following class to your project:


    public class Product
        private Dictionary<string, object> propBag = new Dictionary<string, object>();

        public int ProductID { get; set; }
        public string ProductName { get; set; }
        public int UnitsInStock { get; set; }

        public IDictionary<string, object> PropBag { get { return propBag; } }


Finally, add the following to Program.Main:

        static void Main(string[] args)
            WebDataContext context = new WebDataContext("http://localhost:18752/Northwind.svc");

            var query = from p in context.CreateQuery<Product>("Products")
                        where p.UnitsInStock > 100
                        select p;

            foreach (Product p in query)
                Console.WriteLine(p.ProductName + " , UnitsInStock= " + p.UnitsInStock);



To get both projects to start up for debugging, select Solution-> Properties and select Multiple startup projects with the Action of Start.

Put a breakpoint on the foreach statement in the client app, and hit F5.


If you hover over the query variable, you will actually see the Astoria URI which the Linq query is translated into by the Astoria client library:


So, there you go.  Linq to Astoria’s RESTFUL API.  In other words, Linq to REST. 

In future posts, I will explain how that worked.  What all the Linq capabilities that are supported.  And what one can do with the objects once they are materialized.

Comments (23)

  1. While we worked hard to make it such that any HTTP client can easily consume an ADO.NET Data Service,

  2. While we worked hard to make it such that any HTTP client can easily consume an ADO.NET Data Service

  3. The latest Astoria / ADO.NET Data Services CTP also includes a client-side library with support for creating…

  4. Paul says:

    Is there a trick to get Linq to Sql DataContext to work with the Data Service?  I was not able to get my Linq to Sql context to work.

  5. aconrad says:

    No trick.  What issue are you having?

  6. Link Listing – December 11, 2007

  7. Sam Gentile says:

    Prodded by Mike to pick up the slack, I am trying to get one of these out each morning before all my

  8. You’ve been kicked (a good thing) – Trackback from

  9. Paul says:

    I had to add DataWebKeyAttribute to my primary keys to get the data.svc default page to show anything.  Then when i do data.svc/entity, i don’t get anything.  Is there some pattern it is looking for?  

  10. aconrad says:

    Did you modify the InitializeService method in your data service to allow access to your EntitySets?

  11. dd says:

    What about Astoria and SOA approach? I wonder that this is the architecture we should use in the future. Is it not easier to query database without of using of data services?

    This is for sure sexy, but if I expose the data over http:80, then I have some reason. It could be interoperability. But, by just exposing the data, I’m not sure that we in this case use contract-first approach. Do we have to use is all?

    Oohh I almost forgotten, that BizTalk can do it similar way by using of WCF adapters. Things are getting confused. I do not want be destructive, but I have a feeling, that we will soon see many, many bad applications build on top of great technologies.

  12. Linq to REST 正確にはLINQ to ADO.NET Data Services のようです。 で、これを使うとADO.NET Data Servicesが提供するデータの取得/追加/更新/削除ができるようですね。…

  13. Tim Fischer says:

    This worked fine for reading. I had an issues with getting it working for the update of an entity. I got an server erorr when updating with AppendOnly Tracking.

    Any ideas?

  14. こんにちは、こだかです。 オフラインセミナーも終わりまして、ようやく新しい情報をキャッチアップできるようにと思っていた矢先ですが、前述のVS2008のイベント準備などもあり、思うように時間がとれません。

  15. こんにちは、こだかです。 オフラインセミナーも終わりまして、ようやく新しい情報をキャッチアップできるようにと思っていた矢先ですが、前述のVS2008のイベント準備などもあり、思うように時間がとれません

  16. aconrad says:

    Tim – to get updating to work over Linq to Sql you will need to implement IUpdateable for your DataContext.  I am planning a post in the near future to show how to do this.

  17. Thanks to everyone who came to my session, hope you enjoyed it. First off, instead of slides I used WPF

  18. Steve Herbert has an interesting performance evaluation discussion up on his blog (this is raw LINQ,

  19. ASPInsiders says:

    Someone emailed me recently saying that they couldn’t find enough examples in .NET for talking to the

  20. Alex Black says:

    I’d love to see a follow up to this!

    I am particularily interested in the LINQ aspect.  

    Are there any plans to support other LINQ operations over rest? E.g. joins, selects, group by etc?  It looks like you support where, and skip and take etc only.

    I’ve been exposing data via method calls using WCF, which works great, but I have to decide (ahead of time) how the clients want to use the data.  

    For example, say we have Albums and Songs (with a many to many relationship).  If the client wants to get albums and all of their songs, or songs and all or their albums, in just 1 call (to save round tripping), then I need a method for each of those.

    It’d be much better just to expose LINQ to the client, and execute the linq statement server side to get the data they want.

    This project looks very interesting:

    • Alex
  21. Prodded by Mike to pick up the slack, I am trying to get one of these out each morning before all my work REST/Astoria/Web Programming/Web Services Christian shows how to access SSDL (ADO.NET Entity Framework’s s tore s chema d efinition l anguage and

  22. ASPInsiders says:

    I’ve given a number of presentations on ADO.NET Data Services (formerly codenamed: &quot;Astoria&quot;)