Welcome to MSDN Blogs Sign in | Join | Help

Man vs Code

invaluable minutiae

Syndication

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 ADO.net 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:

image 

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

image 

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

image  

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

image

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="http://www.w3.org/2005/Atom" xmlns:app="http://www.w3.org/2007/app" xmlns="http://www.w3.org/2007/app">
    <workspace>
       <atom:title>Default</atom:title> 
       <collection href="Categories">
         <atom:title>Categories</atom:title> 
       </collection>
       <collection href="Products">
         <atom:title>Products</atom:title> 
       </collection>
       <collection href="Suppliers">
         <atom:title>Suppliers</atom:title> 
       </collection>
    </workspace>
  </service>

 

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:

image

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:

 

    [OpenObject("PropBag")]
    public class Product
    {
        private Dictionary<string, object> propBag = new Dictionary<string, object>();

        [Key]
        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.

image

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:

http://localhost:18752/Northwind.svc/Products?$filter=(UnitsInStock)%20gt%20(100)

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.

Published Monday, December 10, 2007 6:44 PM by aconrad

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# Untitled 1 @ Monday, December 10, 2007 10:24 PM

PingBack from http://www.absolutely-people-search.info/?p=5514

Untitled 1

# LINQ to ADO.NET Data Services @ Tuesday, December 11, 2007 3:33 AM

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

Project Astoria Team Blog

# LINQ to ADO.NET Data Services @ Tuesday, December 11, 2007 3:48 AM

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

Noticias externas

# LINQ-to-REST @ Tuesday, December 11, 2007 9:29 AM

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

Christian Weyer: Smells like service spirit

# re: Linq to REST @ Tuesday, December 11, 2007 11:14 AM

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.

Paul

# re: Linq to REST @ Tuesday, December 11, 2007 4:22 PM

No trick.  What issue are you having?

aconrad

# Link Listing - December 11, 2007 @ Wednesday, December 12, 2007 1:22 AM

Link Listing - December 11, 2007

Christopher Steen

# New and Notable 210 @ Wednesday, December 12, 2007 8:54 AM

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

Sam Gentile

# Remote Execution of LINQ using RESTful API @ Wednesday, December 12, 2007 5:31 PM

You've been kicked (a good thing) - Trackback from DotNetKicks.com

DotNetKicks.com

# re: Linq to REST @ Thursday, December 13, 2007 12:06 PM

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?  

Paul

# re: Linq to REST @ Thursday, December 13, 2007 1:44 PM

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

aconrad

# re: Linq to REST @ Thursday, December 13, 2007 4:27 PM

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.

dd

# LINQ to REST? @ Friday, December 14, 2007 5:24 AM

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

どっとねっとふぁんBlog

# re: Linq to REST @ Saturday, December 15, 2007 7:08 AM

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?

Tim Fischer

# いろいろご紹介 @ Tuesday, December 18, 2007 12:39 PM

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

こだかたろうです

# いろいろご紹介 @ Tuesday, December 18, 2007 12:45 PM

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

Noticias externas

# re: Linq to REST @ Tuesday, December 18, 2007 1:25 PM

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.

aconrad

# Links and Code from my Code Camp Session @ Monday, January 28, 2008 1:26 PM

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

Bryant Likes's Blog

# LINQ Performance - In Memory Collection @ Tuesday, February 12, 2008 6:27 AM

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

Hilton Giesenow's Jumbled Mind

# The Weekly Source Code 22 - C# and VB .NET Libraries to Digg, Flickr, Facebook, YouTube, Twitter, Live Services, Google and other Web 2.0 APIs @ Wednesday, March 26, 2008 8:49 PM

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

ASPInsiders

# re: Linq to REST @ Wednesday, August 06, 2008 12:16 AM

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: http://www.codeplex.com/interlinq

- Alex

Alex Black

# New and Notable 210 @ Tuesday, December 02, 2008 7:05 PM

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

Sam Gentile's Blog

# Real World Apps in Days not Weeks @ Thursday, January 15, 2009 9:26 PM

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

ASPInsiders

Leave a Comment

(required) 
required 
(required) 

  
Enter Code Here: Required
Page view tracker