<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Meta-Me</title><link>http://blogs.msdn.com/b/alexj/</link><description /><dc:language>en-US</dc:language><generator>Telligent Community 5.6.583.20496 (Build: 5.6.583.20496)</generator><item><title>CQRS with OData and Actions?</title><link>http://blogs.msdn.com/b/alexj/archive/2012/02/03/cqrs-with-odata-and-actions.aspx</link><pubDate>Fri, 03 Feb 2012 23:23:35 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10263906</guid><dc:creator>Alex D James</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/alexj/rsscomments.aspx?WeblogPostID=10263906</wfw:commentRss><comments>http://blogs.msdn.com/b/alexj/archive/2012/02/03/cqrs-with-odata-and-actions.aspx#comments</comments><description>&lt;p&gt;I love the Actions feature in OData – which is hardly surprising given I was one of its designers.&amp;#160; &lt;br /&gt;    &lt;br /&gt;Here’s the main reason why I love it: Actions allow you move from a CRUD architecture style, where you query and modify data using the same model, to an architectural style where you have a clear separation between the model used to query and the model used to update. To me this feels a lot like &lt;a href="http://codebetter.com/gregyoung/"&gt;Greg Young&lt;/a&gt;’s baby CQRS, or &lt;a href="http://martinfowler.com/bliki/CQRS.html"&gt;Command Query Responsibility Segregation&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;I’ll admit I’m taking some liberties here because these two models are actually ‘merged’ into a single metadata document ($metadata) that describes them both, and you can share types between these two models… however this feels insignificant because the key benefits remain.&lt;/p&gt;  &lt;p&gt;Why would you want to move from a CRUD style application to a CQRS style one?&lt;/p&gt;  &lt;p&gt;Let’s look at a simple scenario, imagine you have Products that look like this:&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" face="Consolas"&gt;public class Product      &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160; public int ID {get;set;}       &lt;br /&gt;&amp;#160;&amp;#160; public string Name {get;set;}       &lt;br /&gt;&amp;#160;&amp;#160; public Decimal Cost {get;set;}       &lt;br /&gt;&amp;#160;&amp;#160; public Decimal Price {get;set;}       &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;And imagine you want to Discount Marmite (a product in your catalog) by 15%. Today using the CRUD style, the default in OData before Actions, there is only one option: you PUT a new version of the Marmite resource with the new Price to the URL that represents Marmite, i.e. something like this:&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" face="Consolas"&gt;POST ~/Products(15) HTTP/1.1      &lt;br /&gt;Content-Type: application/json       &lt;br /&gt;      &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160; &lt;font color="#9bbb59"&gt;// abbreviated for readability        &lt;br /&gt;&lt;/font&gt;&amp;#160;&amp;#160; “ID”: 15,       &lt;br /&gt;&amp;#160;&amp;#160; “Name”: “Marmite”,       &lt;br /&gt;&amp;#160;&amp;#160; “Cost”: 3.50,       &lt;br /&gt;&amp;#160;&amp;#160; “Price”: &lt;font color="#ff0000"&gt;4.25&lt;/font&gt;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#9bbb59"&gt;// ($5 – 15%)&lt;/font&gt;&amp;#160; &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Notice to support this you have to allow PUT for Products. And this has some real issues:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;People can now make changes that we don’t necessarily want to allow, i.e. modifying the Name &amp;amp; Cost or changing the Price too much.      &lt;ul&gt;       &lt;li&gt;Basically “Update Product” is NOT the same as “Discount Product”. &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;When a change comes through we don’t actually know it is a Discount. It just looks like an attempt to update a Product. &lt;/li&gt;    &lt;li&gt;If you need information that is not part of Product to perform a Discount (perhaps a justification) there is no where to put that information. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;   &lt;br /&gt;More generally the CRUD model is painful because:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;If you want to update lots of resources simultaneously, imagine for example that you want to discount every product in a particular category, you first have to retrieve every product in that category, and then you have to do a PUT for each of them. This of course introduces a lot of unnecessary latency and introduces consistency challenges (it is hard to maintain a transaction boundary across requests &amp;amp; it the longer the ‘transaction’ lasts the more likely a concurrency check will fail). &lt;/li&gt;    &lt;li&gt;If you want to update something you have to allow it to be read somewhere. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;   &lt;br /&gt;Back to our scenario, it would be much better to disable PUT completely and create a Discount action, and advertise it’s availability in the Marmite resource (to keep your system as Hypermedia driven as possible):&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" face="Consolas"&gt;{      &lt;br /&gt;&amp;#160; “__metadata”: {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // abbreviated for simplicity       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; “Actions”: {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; “#MyActions.Discount”: [{ “title”: “Discount Marmite”, “target”: “Products(15)/Discount”}]       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160; &lt;/font&gt;&lt;font color="#0000ff" face="Consolas"&gt;},&amp;#160; &lt;br /&gt;&amp;#160; “ID”: 15,       &lt;br /&gt;&amp;#160; “Name”: “Marmite”,       &lt;br /&gt;&amp;#160; “Cost”: 3.50,       &lt;br /&gt;&amp;#160; “Price”: 5.00       &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;The name of the Action (i.e. #MyActions.Discount) is an ‘anchor’ into the metadata document that can be found at ~/$metadata that says you need to provide a percentage.&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" face="Consolas"&gt;POST ~/Products(15)/Discount HTTP/1.1      &lt;br /&gt;Content-Type: application/json&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" face="Consolas"&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; “percentage”: 15       &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;This is much better. Notice this doesn’t allow me to modify the Cost or the Name, and indeed can easily be validated to make sure the percentage is within an acceptable range, and it is semantically much clearer what is happening.&lt;/p&gt;  &lt;p&gt;In fact by moving from a CRUD style architecture to one inspired by CQRS but based on actions you can:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Give targeted update capabilities that:      &lt;ul&gt;       &lt;li&gt;Allow only certain parts of the ‘Read’ model to be modified. &lt;/li&gt;        &lt;li&gt;Allow things that are not even in the ‘Read’ model to be modified or provided if needed. &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;Selectively give users permissions to only the ‘Actions’ or Commands they need. &lt;/li&gt;    &lt;li&gt;Log every Action and replay them at a later date to rebuild your data (i.e. Event Sourcing). &lt;/li&gt;    &lt;li&gt;Capture what is requested (i.e. Discount the product) and respond immediately before the change has actually been made, safe in the knowledge you will eventually process the request and achieve “Eventual Consistency”. &lt;/li&gt;    &lt;li&gt;Capture more information about what is happening (i.e. User X discounted Marmite by 15% is much better than User X updated Marmite). &lt;/li&gt;    &lt;li&gt;Create Actions that manipulate a lot of entities simultaneously (i.e. POST ~/Categories(‘Yeast Spreads’)/Products/Discount…) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;   &lt;br /&gt;Of course simply separating the read/write models in OData doesn’t give you all of these advantages immediately, but at least it creates a foundation that can scale to support things like Event Sourcing or Eventual Consistency later if required. &lt;/p&gt;  &lt;p&gt;Some of you may be thinking you can achieve many of these goals by having a more granular model that makes things like “Discount” a resource, and that would be true. However for most people using OData that way of thinking is foreign and more importantly the EDM foundations of OData get in the way a little too. So for me Actions seems like the right approach in OData.&lt;/p&gt;  &lt;p&gt;I love this.    &lt;br /&gt;But what do you think?     &lt;br /&gt;-&lt;a href="http://twitter.com/adjames"&gt;Alex&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10263906" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/alexj/archive/tags/OData/">OData</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/CQRS/">CQRS</category></item><item><title>Judgment</title><link>http://blogs.msdn.com/b/alexj/archive/2011/06/07/judgment.aspx</link><pubDate>Tue, 07 Jun 2011 06:20:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10171941</guid><dc:creator>Alex D James</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/alexj/rsscomments.aspx?WeblogPostID=10171941</wfw:commentRss><comments>http://blogs.msdn.com/b/alexj/archive/2011/06/07/judgment.aspx#comments</comments><description>&lt;p&gt;In my last post I blithely said '&lt;a href="http://blogs.msdn.com/controlpanel/b/alexj/archive/2011/06/03/how-do-i-do-design.aspx"&gt;This
is where judgment comes in...&lt;/a&gt;'. &lt;/p&gt;
&lt;p&gt;Unfortunately judgment isn't easy.&lt;/p&gt;
&lt;p&gt;Now when I was younger - say 10 years ago - I was sure about
everything - not least my latest harebrained API design. I chalk that up to
inexperience and not knowing better.&lt;/p&gt;
&lt;p&gt;But now after 15 years of making design mistakes I have a
lot more experience. So much so that I can literally see problems with almost
every design. A big part of this is experience morphing into instinct.&lt;/p&gt;
&lt;p&gt;Instinct is very useful because it helps weed out absurd
ideas quickly. But instinct has limits. It is not much use if you are feeling
equally uneasy about 3 possible designs. &lt;/p&gt;
&lt;p&gt;You need to realize your instincts are based on all your
experiences, and no one project encompasses all your experiences. Which means you can easily
can fooled into thinking something matters when it really doesn't.&lt;/p&gt;
&lt;p&gt;For example if you feel uneasy about one of the possible
solutions because it looks inefficient. It might be your 'performance is important
instinct' kicking in. If you are working on a website expected to get millions
of hits a day, that is a valid concern. But if this is a departmental app with
10 users who each hit the site no more than 10 times a day, then probably not
so much.&lt;/p&gt;
&lt;p&gt;I know this performance example is contrived, but believe me
often it won't be so obvious. You need a reliable way to discard irrelevant concerns
and focus on the real issues.&lt;/p&gt;
&lt;p&gt;The best way to do this is to have a set of guiding
principles for every project you work on. Things like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Simplicity is a feature&lt;/li&gt;
&lt;li&gt;Predictability &amp;amp; Uniformity&lt;/li&gt;
&lt;li&gt;Embrace existing standards&lt;/li&gt;
&lt;li&gt;Payload Driven (HATEOS)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Creating a list like this gives you something more concrete
than instincts to test when you get that uneasy feeling. &lt;/p&gt;
&lt;p&gt;If you have an uneasy feeling you simple ask yourself, Does this
violate any of my projects guiding principles? &lt;/p&gt;
&lt;p&gt;I generally find that uneasy feelings will vanish or become
showstoppers when you do this.&lt;br /&gt;
Enough so that you'll be much more comfortable making a choice...&lt;/p&gt;
&lt;p&gt;... perhaps even the right choice!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10171941" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Design/">Design</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Instincts/">Instincts</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Principles/">Principles</category></item><item><title>How do I do design?</title><link>http://blogs.msdn.com/b/alexj/archive/2011/06/03/how-do-i-do-design.aspx</link><pubDate>Fri, 03 Jun 2011 21:14:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10171238</guid><dc:creator>Alex D James</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/alexj/rsscomments.aspx?WeblogPostID=10171238</wfw:commentRss><comments>http://blogs.msdn.com/b/alexj/archive/2011/06/03/how-do-i-do-design.aspx#comments</comments><description>&lt;p&gt;&lt;span style="font-size: small"&gt;For a while now I've been thinking that the best way to get better at API &amp;amp; protocol design is to try to articulate how you do design.&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;Articulating your thought process has a number of significant benefits:      &lt;br /&gt;&lt;/span&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;span style="font-size: small"&gt;Once you know your approach you can critique and try to improve it.&lt;/span&gt; &lt;/li&gt;    &lt;li&gt;&lt;span style="font-size: small"&gt;Once you know what you'd like to do, in a collaborative setting you can ask others for permission to give it a go. In my experience phrases like &lt;i&gt;&amp;quot;I'd like to explore how this is similar to LINQ ...&amp;quot;&lt;/i&gt; work well if you want others to brainstorm with you.&lt;/span&gt; &lt;/li&gt;    &lt;li&gt;&lt;span style="font-size: small"&gt;Once you understand what you do perhaps you can teach or mentor.&lt;/span&gt; &lt;/li&gt;    &lt;li&gt;&lt;span style="font-size: small"&gt;Or perhaps others can teach you.&lt;/span&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;     &lt;br /&gt;Clearly these are compelling.&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;So I thought I'd give this a go by trying to document an &lt;em&gt;idealized&lt;/em&gt; version of the thought process for Any/All in OData...&lt;/span&gt;&lt;/p&gt;  &lt;h1&gt;The Problem&lt;/h1&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;OData had no way to allow people to query entities based on properties of a related collection, and a &lt;a href="http://data.uservoice.com/forums/72027-wcf-data-services-feature-suggestions"&gt;lot of people&lt;/a&gt;, myself included, wanted to change this...&lt;/span&gt; &lt;/p&gt;  &lt;h1&gt;Step 1: Look for inspiration&lt;/h1&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;I always look for things that I can borrow ideas from. Pattern matching, if you will, with something proven. Here you are limited only by your experience and imagination, there is an almost limitless supply of inspiration. The broader your experience the more source material you have and the higher the probability you will be able to see a useful pattern. &lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;&lt;/span&gt;&lt;span style="font-size: small"&gt;If you need it – and you shouldn’t - this is just another reason to keep learning new languages, paradigms and frameworks! &lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;Sometimes there is something obvious you can pattern match with, other times you really have to stretch...&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;In this case the problem is really easy. Our source material is LINQ. LINQ already allows you to write queries like this:&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="color: #0000ff"&gt;&lt;span style="font-family: consolas; font-size: small"&gt;from movie in Movies        &lt;br /&gt;where movie.Actors.Any(a =&amp;gt; a.Name == 'Zack')         &lt;br /&gt;select movie;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: small"&gt;&amp;#160;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;Which filters movies by the actors (a related collection) in the movie, and that is exactly what we need in OData.&lt;/span&gt; &lt;/p&gt;  &lt;h1&gt;Step 2: Translate from source material to problem domain&lt;/h1&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;My next step is generally to take the ideas from the source material and try to translate them to my problem space. As you do this you'll start to notice the differences between source and problem, some insignificant, some troublesome. &lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;This is where judgment comes in, you need to know when to go back to the drawing board. For me I know I'm on thin ice if I start saying things like &lt;i&gt;'well if I ignore X and Y, and imagine that Z is like this'&lt;/i&gt; .&lt;/span&gt;&lt;span style="font-size: small"&gt;&amp;#160;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;But don't give up too early either. Often the biggest wins are gained by comparing things that seem quite different until you look a little deeper and find a way to ignore the differences that don't really matter. For example Relational Databases and the web seem very different, until you focus on &lt;/span&gt;&lt;a href="http://dl.dropbox.com/u/361389/Base4Blog/Post-036.htm"&gt;&lt;span style="font-size: small"&gt;ForeignKeys vs Hyperlinks&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size: small"&gt;, pull vs push seems different until you read about &lt;/span&gt;&lt;a href="http://channel9.msdn.com/Shows/Going+Deep/Bart-De-Smet-Observations-on-IQbservable-The-Dual-of-IQueryable"&gt;&lt;span style="font-size: small"&gt;IQueryable vs IObservable&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size: small"&gt;.&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;Notice not giving up here is all about having tolerance for ambiguity, the higher your tolerance, the further you can stretch an idea. Which is vital if you want to be really creative. &lt;/span&gt;&lt;span style="font-size: small"&gt;&amp;#160;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;In the case of Any/All it turns out that the inspiration and problem domain are very similar, and the differences are insignificant.&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;So how do you do the translation? &lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;In OData predicate filters are expressed via $filter, so we need to convert this LINQ predicate:&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="color: #0000ff"&gt;&lt;span style="font-size: small"&gt;&lt;span style="font-family: consolas"&gt;(movie) =&amp;gt; movie.Actors.Any(actor =&amp;gt; actor.Name == 'Zack')&lt;/span&gt;&amp;#160;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: small"&gt;&amp;#160;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;into something we can put in an OData $filter. &lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;Let's attack this systematically from left to right. In LINQ you need to name the lambda variable in the predicate, i.e. movie, but in OData there is no need to name the thing you are filtering, it is implicit, for example this:&lt;/span&gt;&lt;span style="font-size: small"&gt;&amp;#160;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="color: #0000ff"&gt;&lt;span style="font-family: consolas; font-size: small"&gt;from movie in Movies        &lt;br /&gt;where movie.Name == &amp;quot;Donnie Darko&amp;quot;         &lt;br /&gt;select movie&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;is expressed like this in OData:      &lt;br /&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-family: consolas; font-size: small"&gt;&lt;span style="color: #0000ff"&gt;       &lt;br /&gt;~/Movies/?$filter=Name eq 'Donnie Darko'&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;Notice there is no variable name, we access the Name of the movie implicitly.&lt;/span&gt;&lt;span style="font-size: small"&gt;&amp;#160;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;So we can skip the ‘movie’.&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;Next in LINQ the Any method is a built-in extension method called directly off the collection using '.Any'. In OData '/' is used in place of '.', and built-in methods are all lowercase, so that points are something like this:&lt;/span&gt;&lt;span style="font-size: small"&gt;&amp;#160;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="color: #0000ff"&gt;&lt;span style="font-family: consolas; font-size: small"&gt;~/Movies/?$filter=Actors/any(????)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;As mentioned previously in OData we don't name variables, everything is implicit. Which means we can ignore the actor variable. That leaves only the filter, which we can convert using existing LINQ to OData conversion rules, to yield something like this:&lt;/span&gt;&lt;span style="font-size: small"&gt;&amp;#160;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="color: #0000ff"&gt;&lt;span style="font-family: consolas; font-size: small"&gt;~/Movies/?$filter=Actors/any(Name eq 'Zack')&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;h1&gt;Step 3: Did you lose something important?&lt;/h1&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;There is a good chance you lost something important in this transformation, so my next step is generally to assess what information has been lost in translation. Paying particular attention to things that are important enough that your source material had specific constructs to capture them.&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;As you notice these differences you either need to convince yourself the differences don’t matter, or you need to add something new to your solution to bring it back.&lt;/span&gt;&lt;span style="font-size: small"&gt;&amp;#160;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;In our case you'll remember that in LINQ the actor being tested in the Any method had a name (i.e. 'actor'), yet in our current OData design it doesn't.&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;Is this important?&lt;/span&gt;&lt;span style="font-size: small"&gt;&amp;#160;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;Yes it is! Unlike the root filter, where there is only one variable in scope (i.e. the movie), inside an Any/All there are potentially two variables in scope (i.e. the movie and the actor). And if neither are named we won't be able to distinguish between them!&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;&lt;/span&gt;&lt;span style="font-size: small"&gt;For example this query, which finds any movies with the same name as any actors who star in the movie, is unambiguous in LINQ:&lt;/span&gt;&lt;span style="font-size: small"&gt;&amp;#160;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="color: #0000ff"&gt;&lt;span style="font-family: consolas; font-size: small"&gt;from movie in Movies        &lt;br /&gt;where movie.Actors.Any(actor =&amp;gt; actor.Name == movie.Name)         &lt;br /&gt;select movie;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;But our proposed equivalent is clearly nonsensical:&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="color: #0000ff"&gt;&lt;span style="font-family: consolas; font-size: small"&gt;~/Movies/?$filter=Actors/any(Name eq Name)&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: small"&gt;&amp;#160;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;It seems we need a way to refer to both the inner (actor) and outer variables (movie) explicitly. &lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;Now we can't change the way existing OData queries work - without breaking clients and servers already deployed - which means we can't explicitly name the outer variable, we can however introduce a way to refer to it implicitly. This should be a reserved name so it can't collide with any properties. OData already uses the $ prefix for reserved names (i.e. $filter, $skip etc) so we could try something like $it . This results in something like this:&lt;/span&gt;&lt;span style="font-size: small"&gt;&amp;#160;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="color: #0000ff"&gt;&lt;span style="font-family: consolas; font-size: small"&gt;~/Movies/?$filter=Actors/any(Name eq $it/Name)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;And now the query is unambiguous again.&lt;/span&gt;&lt;span style="font-size: small"&gt;&amp;#160;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;But unfortunately we aren't done yet. We need to make sure nesting works calls works too, for example this:&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="color: #0000ff"&gt;&lt;span style="font-family: consolas; font-size: small"&gt;from movie in Movies        &lt;br /&gt;where movie.Actors.Any(actor =&amp;gt; actor.Name == movie.Name &amp;amp;&amp;amp; actor.Awards.Any(award =&amp;gt; award.Name == 'Oscar'))         &lt;br /&gt;select movie;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;If we translate this, with the current design we get this:&lt;/span&gt;&lt;span style="font-size: small"&gt;&amp;#160;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="color: #0000ff"&gt;&lt;span style="font-family: consolas; font-size: small"&gt;~/Movies/?$filter=Actors/any(Name eq $it/Name AND Awards/any(Name eq 'Oscar'))&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;But now it is unclear whether &lt;span style="font-family: consolas"&gt;Name eq 'Oscar'&lt;/span&gt; refers to the actor or the award. Perhaps we need to be able to name the actor and award variables too. Here we are not restricted by the past, Any/All is new, so it can include a way to explicitly name the variable. Again we look at LINQ for inspiration:&lt;/span&gt;&lt;span style="font-size: small"&gt;&amp;#160;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="color: #0000ff"&gt;&lt;span style="font-family: consolas; font-size: small"&gt;award =&amp;gt; award.Name == 'Oscar'&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;Cleary we need something like '=&amp;gt;' that is URI friendly and compatible with the current OData design. It turns out ':' is a good candidate, because it works well in querystrings, and isn’t currently used by OData, and even better there is a precedent in Python lambda’s (notice the pattern matching again). So the final proposal is something like this:&lt;/span&gt;&lt;span style="font-size: small"&gt;&amp;#160;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="color: #0000ff"&gt;&lt;span style="font-family: consolas; font-size: small"&gt;~/Movies/?$filter=Actors/any(actor: actor/Name eq $it/Name)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;Or for the nested scenario:&lt;/span&gt;&lt;span style="font-size: small"&gt;&amp;#160;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="color: #0000ff"&gt;&lt;span style="font-family: consolas; font-size: small"&gt;~/Movies/?$filter=Actors/any(actor: actor/Name eq $it/Name AND actor/Awards/any(award: award/Name eq 'Oscar'))&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-family: segoe; font-size: small"&gt;And again nothing is ambiguous.&lt;/span&gt;&lt;/p&gt;  &lt;h1&gt;Step 4: Rinse and Repeat&lt;/h1&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;In this case the design feels good, so we are done.&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;But clearly that won't always be the case. However you should at least know whether the design is looking promising or not. If not it is back to the drawing board. &lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;If it does look promising, I would essentially repeat steps 1-3 again using some other inspiration to inform further tweaking of the design, hopefully to something that feels complete.&lt;/span&gt;&lt;/p&gt;  &lt;h1&gt;Conclusion&lt;/h1&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;While writing this up I definitely teased out a number of things that had previously been unconscious, and I sure this will help me going forward, hopefully you too? &lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;Next time I do this I'll explore something that involves more creativity... and I'll try to tease out more of the unconscious tools I use.&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;What do you think about all this? Do you have any suggested improvements?&lt;/span&gt;&lt;span style="font-size: small"&gt;&amp;#160;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: small"&gt;-&lt;a href="http://twitter.com/adjames"&gt;Alex&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10171238" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Learning/">Learning</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Design/">Design</category></item><item><title>TechEd 2010 Videos</title><link>http://blogs.msdn.com/b/alexj/archive/2010/06/12/teched-2010-videos.aspx</link><pubDate>Sat, 12 Jun 2010 16:05:11 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10023945</guid><dc:creator>Alex D James</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/alexj/rsscomments.aspx?WeblogPostID=10023945</wfw:commentRss><comments>http://blogs.msdn.com/b/alexj/archive/2010/06/12/teched-2010-videos.aspx#comments</comments><description>&lt;p&gt;If you didn't get to TechEd - no problem - videos of all the sessions are available &lt;a href="http://www.msteched.com/"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Including my &lt;a href="http://www.msteched.com/2010/NorthAmerica/DEV323"&gt;Best Practices: Creating an OData Service using WCF Data Services session&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you watch that video and want to follow try it out - you can &lt;a href="http://blogs.msdn.com/b/alexj/archive/2010/06/11/odata-wcf-data-services-best-practices-from-teched.aspx"&gt;download all the source code I uploaded previously&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Enjoy.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10023945" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Data+Services/">Data Services</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/OData/">OData</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/TechEd2010/">TechEd2010</category></item><item><title>Tip 56 - Writing an OData Service using the Reflection Provider</title><link>http://blogs.msdn.com/b/alexj/archive/2010/06/11/tip-56-writing-an-odata-service-using-the-reflection-provider.aspx</link><pubDate>Fri, 11 Jun 2010 18:05:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10023648</guid><dc:creator>Alex D James</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/alexj/rsscomments.aspx?WeblogPostID=10023648</wfw:commentRss><comments>http://blogs.msdn.com/b/alexj/archive/2010/06/11/tip-56-writing-an-odata-service-using-the-reflection-provider.aspx#comments</comments><description>&lt;p&gt;At TechEd I got a lot of questions about how to expose Data as OData&lt;/p&gt;
&lt;p&gt;By now you probably know you can use Data Services&amp;nbsp;and the Entity Framework to expose&amp;nbsp;data from a database&amp;nbsp;as an OData Service. You might even know you can use Data Services with a custom Data Service Provider to expose arbitrary data from anywhere.&lt;/p&gt;
&lt;p&gt;But did you know about the Data Services Reflection provider?.&lt;/p&gt;
&lt;p&gt;Turns out&amp;nbsp;reflection provider &amp;nbsp;is VERY simple to use.&lt;/p&gt;
&lt;p&gt;To show you just how simple I am going to create an odata service to expose some in memory data. &lt;/p&gt;
&lt;p&gt;First you need some data, so how about this topical data:&lt;/p&gt;
&lt;pre&gt;&lt;p&gt;[EntityPropertyMapping("Name", &lt;br /&gt;                        SyndicationItemProperty.Title, &lt;br /&gt;                        SyndicationTextContentKind.Plaintext, &lt;br /&gt;                        false)]&lt;br /&gt;[EntityPropertyMapping("Odds", &lt;br /&gt;                        SyndicationItemProperty.Summary, &lt;br /&gt;                        SyndicationTextContentKind.Plaintext, &lt;br /&gt;                        false)]&lt;br /&gt;public class Team {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;   public static List&amp;lt;Team&amp;gt; Teams = new List&amp;lt;Team&amp;gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new Team {ID = 1, Name = "New Zealand", Odds = "1:1000"},&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new Team {ID = 2, Name = "Paraquay", Odds = "1:50"},&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;hellip;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }; &lt;/p&gt;&lt;br /&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public int ID{get;set;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public string Name {get;set;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string Odds { get; set; }&lt;br /&gt;}&lt;/p&gt;&lt;p&gt;[DataServiceKey("Name")]&lt;br /&gt;[EntityPropertyMapping("Name", &lt;br /&gt;                        SyndicationItemProperty.Title,&lt;br /&gt;                        SyndicationTextContentKind.Plaintext, &lt;br /&gt;                        false)]&lt;br /&gt;public class Group&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static List&amp;lt;Group&amp;gt; Groups = new List&amp;lt;Group&amp;gt;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new Group {&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Name = "A",&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Teams = new List&amp;lt;Team&amp;gt;{&amp;nbsp;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Team.Teams[0],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Team.Teams[1],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Team.Teams[2],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Team.Teams[3]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; },&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;      new Group {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Name = "B",&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Teams = new List&amp;lt;Team&amp;gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Team.Teams[4],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Team.Teams[5],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Team.Teams[6],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Team.Teams[7]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;hellip;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; };&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string Name {get;set;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public List&amp;lt;Team&amp;gt; Teams {get;set;}&lt;br /&gt;}&lt;/p&gt;&lt;/pre&gt;
&lt;p&gt;Notice the use of the &lt;span style="font-family: Lucida Console;"&gt;&lt;b&gt;[DataServiceKey]&lt;/b&gt;&lt;/span&gt; and &lt;span style="font-family: Lucida Console;"&gt;&lt;b&gt;[EntityPropertyMapping]&lt;/b&gt;&lt;/span&gt; attributes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="font-family: Lucida Console;"&gt;&lt;b&gt;[DataServiceKey]&lt;/b&gt;&lt;/span&gt; tells Data Services which property(s) is the key. This is only required if the key isn&amp;rsquo;t ID or {ClassName}ID. &lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: Lucida Console;"&gt;&lt;b&gt;[EntityPropertyMapping]&lt;/b&gt;&lt;/span&gt; tells Data Services to map the property to a standard atom element. This is not required &amp;ndash; but it is a best practice &amp;ndash; it makes the resulting feed easier to read in a browser. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Next you need a class to act as your Data Source. Data Services will expose all the IQueryable properties as Feeds and infer types for all the types exposed by those Feeds.&lt;/p&gt;
&lt;p&gt;So if I want two feeds, to expose Groups and Teams from the world cup, I&amp;rsquo;d do it like this:&lt;/p&gt;
&lt;pre&gt;&lt;p&gt;public class WorldCupData&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IQueryable&amp;lt;Team&amp;gt; Teams{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return Team.Teams.AsQueryable();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IQueryable&amp;lt;Group&amp;gt; Groups{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return Group.Groups.AsQueryable();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;/p&gt;&lt;/pre&gt;
&lt;p&gt;Now all you need to do is create the Data Service, and expose our sets. Simply add a WCF Data Service to you web application and modify the generated code to look like this:&lt;/p&gt;
&lt;pre&gt;&lt;p&gt;public class WorldCup : DataService&amp;lt;WorldCupData&amp;gt;&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // This method is called only once to initialize service-wide policies.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static void InitializeService(DataServiceConfiguration config)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; config.SetEntitySetPageSize("*", 100);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;/p&gt;&lt;/pre&gt;
&lt;p&gt;That&amp;rsquo;s it you are done:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-93-87-metablogapi/2477.ReflectionProvider.png"&gt;&lt;img src="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-93-87-metablogapi/3173.ReflectionProvider_5F00_thumb.png" alt="ReflectionProvider" title="ReflectionProvider" style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" width="244" border="0" height="124" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;A couple of points worth noting:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;This service is read-only. If you want to make it read-write you have to implement &lt;a href="http://blogs.msdn.com/b/alexj/archive/2010/02/11/creating-a-data-service-provider-part-7-update.aspx"&gt;IDataServiceUpdateProvider&lt;/a&gt;. &lt;/li&gt;
&lt;li&gt;In this example the data comes from in-memory arrays, however if you have an IQueryable that supports it your data can come from anywhere. &lt;/li&gt;
&lt;li&gt;Yes I know my data is all wrong, I&amp;rsquo;m writing this on a SouthWest flight from New Orleans to Denver with no internet. But thankfully there is a &lt;a href="http://www.openligadb.de/Webservices/OData.svc/"&gt;real OData Service for the World Cup here&lt;/a&gt;. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Enjoy.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10023648" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Tips/">Tips</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Data+Services/">Data Services</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/OData/">OData</category></item><item><title>OData - WCF Data Services Best Practices from TechEd</title><link>http://blogs.msdn.com/b/alexj/archive/2010/06/11/odata-wcf-data-services-best-practices-from-teched.aspx</link><pubDate>Thu, 10 Jun 2010 23:01:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10023246</guid><dc:creator>Alex D James</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/alexj/rsscomments.aspx?WeblogPostID=10023246</wfw:commentRss><comments>http://blogs.msdn.com/b/alexj/archive/2010/06/11/odata-wcf-data-services-best-practices-from-teched.aspx#comments</comments><description>&lt;p&gt;Yesterday I promised to share all the code from my &lt;strong&gt;Best Practices &amp;ndash; Creating an OData Service using WCF Data Services&lt;/strong&gt; session at TechED.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; you can find a recording of that session &lt;a href="http://www.msteched.com/2010/NorthAmerica/DEV323"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So here goes, essentially this is what I did:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Downloaded&lt;/strong&gt;,&lt;strong&gt; unzipped&lt;/strong&gt;,&lt;strong&gt; opened&lt;/strong&gt; and &lt;strong&gt;ran&lt;/strong&gt; the &lt;a href="http://mvcmusicstore.codeplex.com/"&gt;MVC Music Store Sample&lt;/a&gt;.&amp;nbsp; &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Added&lt;/strong&gt; an album to my cart, &lt;strong&gt;registered&lt;/strong&gt; and &lt;strong&gt;ordered&lt;/strong&gt; the album. &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Added&lt;/strong&gt; a data service to that project to expose the Entity Framework model already in the Music Store sample: &lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;&lt;span style="font-family: Lucida Console;"&gt;public class MusicService : DataService&amp;lt;MusicStoreEntities&amp;gt;&lt;/span&gt; &lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Added&lt;/strong&gt; specific EntitySetAccessRules: &lt;br /&gt;&lt;span style="font-family: Lucida Console;"&gt;&lt;br /&gt;// We don&amp;rsquo;t want the Data service to expose carts at all config.SetEntitySetAccessRule( &lt;br /&gt;&amp;nbsp;&amp;nbsp; "Carts", &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; EntitySetRights.None &lt;br /&gt;); &lt;br /&gt;// You can only get 1 OrderDetail at a time &lt;br /&gt;config.SetEntitySetAccessRule( &lt;br /&gt;&amp;nbsp;&amp;nbsp; "OrderDetails", &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; EntitySetRights.ReadSingle &lt;br /&gt;); &lt;br /&gt;// Everything else you can read &amp;amp; query. &lt;br /&gt;config.SetEntitySetAccessRule( &lt;br /&gt;&amp;nbsp;&amp;nbsp; "*",&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp; EntitySetRights.AllRead &lt;br /&gt;); &lt;br /&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Added&lt;/strong&gt; Server Driven Paging limits: &lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: Lucida Console;"&gt;config.SetEntitySetPageSize("*", 5);&lt;/span&gt; &lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Added&lt;/strong&gt; a query interceptor to only allow users to see just the own orders: &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Lucida Console;"&gt;[QueryInterceptor("Orders")] &lt;br /&gt;public Expression&amp;lt;Func&amp;lt;Order, bool&amp;gt;&amp;gt; OrdersFilter() &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var user = HttpContext.Current.User.Identity.Name; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (string.IsNullOrEmpty(user)) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return (Order o) =&amp;gt; false; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; else if (user== "Administrator") &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return (Order o) =&amp;gt; true; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; else &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return (Order o) =&amp;gt; o.Username == user; &lt;br /&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Made&lt;/strong&gt; my service web browser friendly by Configuring the EDMX to map Genre.Name to the Entry/Title and Genre.Description to the Entry/Summary. &lt;br /&gt;&lt;br /&gt;See the EDMX in the &lt;a href="http://dl.dropbox.com/u/361389/TechEd/FinalSourceMVCMusicStore.zip"&gt;final copy of the source&lt;/a&gt; to see how. &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Added&lt;/strong&gt; a &lt;a href="http://dl.dropbox.com/u/361389/TechEd/ClientAccessPolicy.xml"&gt;ClientAccessPolicy.xml&lt;/a&gt; so that Silverlight apps hosted on different sites can interact with our Data Service. &lt;br /&gt;&lt;br /&gt;&lt;span style="color: #808080;"&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; The two sites in question need to be in the same internet zone! &lt;br /&gt;&lt;/span&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Demoed&lt;/strong&gt; using some &lt;a href="http://dl.dropbox.com/u/361389/TechEd/UsingJSON.htm"&gt;JQuery JSON code&lt;/a&gt; that accesses the MusicService from the same site. &lt;br /&gt;&lt;br /&gt;&lt;span style="color: #808080;"&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; this doesn&amp;rsquo;t work x-site, for that you need JSONP. &lt;br /&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Added&lt;/strong&gt; support for JSONP by applying the [DataServicesJSONP.JSONPSupportBehavior] attribute to our MusicService. &lt;br /&gt;&lt;br /&gt;You can &lt;a href="http://code.msdn.microsoft.com/DataServicesJSONP"&gt;download the source&lt;/a&gt; from CodeGallery. &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Demoed&lt;/strong&gt; some &lt;a href="http://dl.dropbox.com/u/361389/TechEd/UsingJSONP.htm"&gt;JQuery JSONP code&lt;/a&gt; that accesses the MusicService from a remote site. &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Configured&lt;/strong&gt; ASP.NET to expose an authentication service, so non-browser agents can easily connect and logon to the Forms Authentication service, by adding this to the web.config: &lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;&lt;span style="font-family: Lucida Console;"&gt;&amp;lt;system.web.extensions&amp;gt; &lt;br /&gt;&amp;nbsp; &amp;lt;scripting&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;webServices&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;authenticationService enabled="true" requireSSL="false"/&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/webServices&amp;gt; &lt;br /&gt;&amp;nbsp; &amp;lt;/scripting&amp;gt; &lt;br /&gt;&amp;lt;/system.web.extensions&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Tested&lt;/strong&gt; the authentication service using &lt;a href="http://www.fiddler2.com/fiddler2/"&gt;Fiddler&lt;/a&gt; by sending this RAW request to authenticate: &lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: Lucida Console;"&gt;POST &lt;/span&gt;&lt;span style="font-family: Lucida Console;"&gt;http://localhost:1397/Authentication_JSON_AppService.axd/Login&lt;/span&gt;&lt;span style="font-family: Lucida Console;"&gt; HTTP/1.1 &lt;br /&gt;Content-Type: application/json &lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: Lucida Console;"&gt;{ "userName": "Alex", "password": "password", "createPersistentCookie":false} &lt;br /&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Opened&lt;/strong&gt; this &lt;a href="http://dl.dropbox.com/u/361389/TechEd/FormsAuthentication.zip"&gt;Data Services client application&lt;/a&gt; to show how to authenticate against the forms authentication service.&lt;/li&gt;

&lt;/ul&gt;&lt;p&gt;You can download the &lt;a href="http://dl.dropbox.com/u/361389/TechEd/FinalSourceMVCMusicStore.zip"&gt;finally copy of the Music Service code&lt;/a&gt; if you want.&lt;/p&gt;
&lt;p&gt;Enjoy and good luck.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10023246" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/alexj/archive/tags/ASP-NET/">ASP.NET</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Data+Services/">Data Services</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Authentication/">Authentication</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/OData/">OData</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/JSON/">JSON</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Data+Services+Client/">Data Services Client</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/TechEd2010/">TechEd2010</category></item><item><title>Creating a Data Service Provider – Part 9 – Un-typed</title><link>http://blogs.msdn.com/b/alexj/archive/2010/03/02/creating-a-data-service-provider-part-9-un-typed.aspx</link><pubDate>Tue, 02 Mar 2010 21:14:57 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9971784</guid><dc:creator>Alex D James</dc:creator><slash:comments>9</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/alexj/rsscomments.aspx?WeblogPostID=9971784</wfw:commentRss><comments>http://blogs.msdn.com/b/alexj/archive/2010/03/02/creating-a-data-service-provider-part-9-un-typed.aspx#comments</comments><description>&lt;p&gt;&lt;font color="#808080"&gt;&lt;strong&gt;Background info:&lt;/strong&gt; This post builds on &lt;a href="http://blogs.msdn.com/alexj/archive/2010/01/07/data-service-providers-getting-started.aspx"&gt;Parts 1 thru 8&lt;/a&gt; which teach you how to create a typed Data Service Provider.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;But now the part we’ve all been waiting for- an un-typed DSP – which is what I expect most real world DSP implementations will be based on. &lt;/p&gt;  &lt;h3&gt;What do we mean by Un-typed?&lt;/h3&gt;  &lt;p&gt;An un-typed DSP is needed whenever there isn’t a matching CLR class for each ResourceType. Typically you there is some general purpose class used for every ResourceType, something like a Dictionary for instance.&lt;/p&gt;  &lt;p&gt;Over the course of the rest of this Post we will look at converting our DSP to expose product and category data stored in two Lists of Dictionaries, i.e. a List for each ResourceSet/Feed and a Dictionary for each Resource.&lt;/p&gt;  &lt;h3&gt;Why Un-typed?&lt;/h3&gt;  &lt;p&gt;Un-typed DSPs have a lot of interesting advantages:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;You don’t need CLR classes for all the different ResourceTypes we want to expose &lt;/li&gt;    &lt;li&gt;You don’t need to recompile / restart the service if the ResourceTypes changes in some way, i.e. you add a new Property. &lt;/li&gt;    &lt;li&gt;You can store a pointer to the metadata for the ResourceType directly in the ResourceType itself. &lt;/li&gt;    &lt;li&gt;You can store extra data along with a Resource very easily, which potentially allows us to take advantage of Data Services support for OpenTypes and OpenProperties. &lt;/li&gt;    &lt;li&gt;You can evolve you model at runtime to expose more ResourceTypes/Sets &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;So now we know why, lets get started.&lt;/p&gt;  &lt;h3&gt;Metadata Changes:&lt;/h3&gt;  &lt;p&gt;The first thing we need to do create all our ResourceTypes:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;var productType = new ResourceType(     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; // CLR type backing this Resource&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; typeof(Dictionary&amp;lt;string,object&amp;gt;),&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; // Entity, ComplexType etc&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ResourceTypeKind.EntityType,&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; null, // BaseType       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;Namespace&amp;quot;, // Namespace       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;Product&amp;quot;, // Name       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; false // Abstract?       &lt;br /&gt;);       &lt;br /&gt;productType.CanReflectOnInstanceType = false;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Note there are two big differences between this and how we did things for Strongly Typed Resource Types (see &lt;a href="http://blogs.msdn.com/alexj/archive/2010/01/08/creating-a-data-service-provider-part-3-metadata.aspx"&gt;part 3&lt;/a&gt;):&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;We tell Data Service that Products are stored in a Dictionary&amp;lt;string,object&amp;gt; &lt;/li&gt;    &lt;li&gt;We tell Data Service that Dictionary&amp;lt;string,object&amp;gt; doesn’t have the same CLR inheritance hierarchy as the ResourceType itself – via CanReflectOnInstanceType.&amp;#160; &lt;br /&gt;This means whenever Casts are required rather than injecting standard CLR casts into the generated Query Expression, Data Services will inject methods calls the underlying injecting query provider is expected to translate. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Next we create our properties just like before:    &lt;br /&gt;    &lt;br /&gt;&lt;font face="Courier New"&gt;var prodKey = new ResourceProperty(      &lt;br /&gt;&amp;#160;&amp;#160; &amp;quot;ProdKey&amp;quot;,       &lt;br /&gt;&amp;#160;&amp;#160; ResourcePropertyKind.Key |       &lt;br /&gt;&amp;#160;&amp;#160; ResourcePropertyKind.Primitive,       &lt;br /&gt;&amp;#160;&amp;#160; ResourceType.GetPrimitiveResourceType(typeof(int))       &lt;br /&gt;);&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;But we add one extra call:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;prodKey.CanReflectOnInstanceTypeProperty = false;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;This tells DataServices that the declaring type – in this case Dictionary&amp;lt;string,object&amp;gt; - doesn’t actually have a “ProdKey” property, so a PropertyAccessor expression can’t be used.&lt;/p&gt;  &lt;p&gt;With this setup this:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;strong&gt;GET ~/Products(2)&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Will no longer produce an (pseudo) expression like this:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;from p in _queryProvider.GetQueryRootForResourceSet(productsSet)      &lt;br /&gt;where p.ProdKey == 2       &lt;br /&gt;select p;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Which would be invalid because ProdKey is not a property of Dictionary&amp;lt;string,object&amp;gt;, instead it will produce something like this:&lt;/p&gt; &lt;font face="Courier New"&gt;from p in _queryProvider.GetQueryRootForResourceSet(productsSet)    &lt;br /&gt;where ((int) DataServiceProviderMethods.GetValue(p,&amp;quot;ProdKey&amp;quot;))    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; == 2&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;select p;&lt;/font&gt;   &lt;p&gt;Which gives your query provider the opportunity to re-write the expression as:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;from p in _queryProvider.GetQueryRootForResourceSet(productsSet)      &lt;br /&gt;where ((int) p[&amp;quot;ProdKey&amp;quot;]) == 2&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;select p;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Which for example LINQ to Objects can handle.&lt;/p&gt;  &lt;p&gt;&lt;font color="#808080"&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; If your data isn’t in memory – maybe it is in a database – you still have to translate this expression into something like SQL, so it might just be easier to do that in one visit.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Once you’ve updated all your types accordingly you should have no problem getting &lt;strong&gt;~/root.svc&lt;/strong&gt; or &lt;strong&gt;~/root.svc/$metadata&lt;/strong&gt; working.&lt;/p&gt;  &lt;h3&gt;Data Source Changes:&lt;/h3&gt;  &lt;p&gt;Next we need to make some changes to our Data Sources so that the data is stored in Dictionaries.&lt;/p&gt;  &lt;p&gt;If you remember we had this abstract base class from which our Data Source should inherit:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;public abstract class DSPContext      &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public abstract IQueryable GetQueryable(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ResourceSet resourceSet);       &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public abstract object CreateResource(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ResourceType resourceType);       &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public abstract void AddResource(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ResourceSet resourceSet, object resource);       &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public abstract void DeleteResource(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; object resource);       &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public abstract void SaveChanges();       &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Tah"&gt;Here is an implementation that works over dictionaries:&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;public class SampleUntypedContext: DSPContext     &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public const string RESOURCE_TYPE_KEY = &amp;quot;_ResourceType&amp;quot;;      &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; static Dictionary&amp;lt;string, List&amp;lt;Dictionary&amp;lt;string, object&amp;gt;&amp;gt;&amp;gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; dataSources =       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; new Dictionary&amp;lt;string, List&amp;lt;Dictionary&amp;lt;string, object&amp;gt;&amp;gt;&amp;gt;{&lt;/font&gt;&lt;font face="Courier New"&gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&amp;quot;Products&amp;quot;, new List&amp;lt;Dictionary&amp;lt;string,object&amp;gt;&amp;gt;()},      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&amp;quot;Categories&amp;quot;, new List&amp;lt;Dictionary&amp;lt;string,object&amp;gt;&amp;gt;()}&amp;#160; &lt;br /&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160; }; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160; public override IQueryable GetQueryable(     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ResourceSet resourceSet)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return GetDataSource(resourceSet.Name).AsQueryable();      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public override void AddResource(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ResourceSet resourceSet, object resource)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; var resourceInstance = GetResourceInstance(resource);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; var instanceTypeName = GetResourceType(resourceInstance);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (instanceTypeName != resourceSet.ResourceType.FullName)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; throw new InvalidOperationException(&amp;quot;Unexpected Resource Type&amp;quot;); &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; var dataSource = GetDataSource(resourceSet.Name);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; dataSource.Add(resourceInstance);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public override void DeleteResource(object resource)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; var resourceInstance = GetResourceInstance(resource);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; var resourceInstanceType = GetResourceType(resource); &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; List&amp;lt;Dictionary&amp;lt;string,object&amp;gt;&amp;gt; datasource = null;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (resourceInstanceType == &amp;quot;Product&amp;quot;)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; datasource = GetDataSource(&amp;quot;Products&amp;quot;);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; else if (resourceInstanceType == &amp;quot;Category&amp;quot;)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; datasource = GetDataSource(&amp;quot;Categories&amp;quot;);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; else      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; throw new Exception(&amp;quot;ResourceSet not found&amp;quot;);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; datasource.Add(resourceInstance);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public override void SaveChanges()      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; var products = GetDataSource(&amp;quot;Products&amp;quot;);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; var categories = GetDataSource(&amp;quot;Categories&amp;quot;); &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; var prodKey = products.Max(p =&amp;gt; (int)p[&amp;quot;ProdKey&amp;quot;]);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; foreach (var prod in products      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; .Where(p =&amp;gt; ((int) p[&amp;quot;ProdKey&amp;quot;])== 0))      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; prod[&amp;quot;ProdKey&amp;quot;] = ++prodKey;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; var catKey = categories.Max(c =&amp;gt; (int)c[&amp;quot;ID&amp;quot;]);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; foreach (var cat in categories      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; .Where(c =&amp;gt; ((int)c[&amp;quot;ID&amp;quot;]) == 0))      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; cat[&amp;quot;ID&amp;quot;] = ++catKey;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; private Dictionary&amp;lt;string, object&amp;gt; GetResourceInstance(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; object obj)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; var x = obj as Dictionary&amp;lt;string, object&amp;gt;;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (x == null || !x.ContainsKey(RESOURCE_TYPE_KEY))      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; throw new InvalidCastException(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;quot;Object is not a resource&amp;quot;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; );      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return x;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; private string GetResourceType(object obj)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; var x = GetResourceInstance(obj);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return x[RESOURCE_TYPE_KEY] as string;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public override object CreateResource(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ResourceType resourceType)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; var instance = new Dictionary&amp;lt;string, object&amp;gt; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; { RESOURCE_TYPE_KEY, resourceType.FullName }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; };      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; foreach (var property in resourceType.Properties)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; instance[property.Name] = GetDefaultValue(property);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return instance;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public static List&amp;lt;Dictionary&amp;lt;string, object&amp;gt;&amp;gt; GetDataSource(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; string resourceSetName)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (!dataSources.ContainsKey(resourceSetName))      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; throw new Exception(&amp;quot;ResourceSet not found&amp;quot;);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return dataSources[resourceSetName];      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; private object GetDefaultValue(ResourceProperty prop)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if ((prop.Kind &amp;amp; ResourcePropertyKind.Primitive)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; == ResourcePropertyKind.Primitive)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (!prop.ResourceType.InstanceType.IsValueType)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return null;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; else      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return Activator.CreateInstance(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; prop.ResourceType.InstanceType      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; );      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; else if (      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; prop.Kind==ResourcePropertyKind.ResourceSetReference      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ){      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return new List&amp;lt;Dictionary&amp;lt;string, object&amp;gt;&amp;gt;();      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; else if (      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; prop.Kind== ResourcePropertyKind.ResourceReference      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ){      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return null;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; throw new NotSupportedException();      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Again you can see that this has some repetitive code that we could be generalize.&lt;/p&gt;  &lt;p&gt;We hold our Lists of Dictionary&amp;lt;string,object&amp;gt; in a Dictionary keyed on the ResourceSet name. &lt;/p&gt;  &lt;p&gt;And &lt;a href="http://blogs.msdn.com/alexj/archive/2010/02/11/creating-a-data-service-provider-part-7-update.aspx"&gt;as before&lt;/a&gt; our SaveChanges() function mimic server generated values for primary keys.&lt;/p&gt;  &lt;p&gt;Perhaps the most interesting function is the implementation of CreateResource which adds all the properties to the Dictionary and assigns default values for each property, mimicking a strongly typed class constructor. &lt;/p&gt;  &lt;p&gt;Now that we have a Data Source we need to fill it with some data. In the typed example we did this by overriding CreateDataSource, so no surprises, we need to do that again:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;protected override SampleUntypedContext CreateDataSource()     &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; var products = SampleUntypedContext      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; .GetDataSource(&amp;quot;Products&amp;quot;);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; var categories = SampleUntypedContext      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; .GetDataSource(&amp;quot;Categories&amp;quot;);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if (products.Count == 0)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; var bovril = new Dictionary&amp;lt;string,object&amp;gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&amp;quot;_ResourceType&amp;quot;, &amp;quot;Namespace.Product&amp;quot;},      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&amp;quot;ProdKey&amp;quot;,&amp;#160; 1},      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&amp;quot;Name&amp;quot;, &amp;quot;Bovril&amp;quot;},      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&amp;quot;Cost&amp;quot;, 4.35M},      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&amp;quot;Price&amp;quot;, 6.49M}      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; };      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; var marmite = new Dictionary&amp;lt;string, object&amp;gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&amp;quot;_ResourceType&amp;quot;, &amp;quot;Namespace.Product&amp;quot;},      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&amp;quot;ProdKey&amp;quot;,&amp;#160; 2},      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&amp;quot;Name&amp;quot;, &amp;quot;Marmite&amp;quot;},      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&amp;quot;Cost&amp;quot;, 4.97M},      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&amp;quot;Price&amp;quot;, 7.21M}      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; };      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; var food = new Dictionary&amp;lt;string, object&amp;gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&amp;quot;_ResourceType&amp;quot;, &amp;quot;Namespace.Category&amp;quot;},      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&amp;quot;ID&amp;quot;,&amp;#160; 1},      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&amp;quot;Name&amp;quot;, &amp;quot;Food&amp;quot;}      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; };      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // Build bi-directional relationships      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; food[&amp;quot;Products&amp;quot;] = new List&amp;lt;Dictionary&amp;lt;string, object&amp;gt;&amp;gt; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; marmite,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; bovril       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; };      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; marmite[&amp;quot;Category&amp;quot;] = food;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; bovril[&amp;quot;Category&amp;quot;] = food;      &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // Store resources      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; products.Add(marmite);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; products.Add(bovril);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; categories.Add(food);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return base.CreateDataSource();      &lt;br /&gt;}      &lt;br /&gt;&lt;/font&gt;&lt;/p&gt;  &lt;h3&gt;IDataServiceMetadataProvider changes:&lt;/h3&gt;  &lt;p&gt;There are no real changes required here, because essentially this is just returning metadata, and the &lt;a href="http://blogs.msdn.com/alexj/archive/2010/01/08/creating-a-data-service-provider-part-3-metadata.aspx"&gt;same code we wrote for the Typed provider&lt;/a&gt; will work still.&lt;/p&gt;  &lt;h3&gt;IDataServiceQueryProvider changes:&lt;/h3&gt;  &lt;p&gt;Here we need to change three things.    &lt;br /&gt;    &lt;br /&gt;The way we work out the ResourceType for a resource:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;public ResourceType GetResourceType(object target)     &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return GetResourceType(GetResource(target)&lt;/font&gt;&lt;font face="Courier New"&gt;);     &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;private Dictionary&amp;lt;string, object&amp;gt; GetResource(object target)     &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; var dict = target as Dictionary&amp;lt;string, object&amp;gt;;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if (dict == null)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;font face="Courier New"&gt;throw new InvalidCastException(     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;quot;Resource is not a dictionary&amp;quot;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; );      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return dict;      &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;private ResourceType GetResourceType(     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Dictionary&amp;lt;string, object&amp;gt; resource)      &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ResourceType type = null;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if (!resource.ContainsKey(&amp;quot;_ResourceType&amp;quot;))       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; throw new InvalidOperationException(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;quot;ResourceType not known&amp;quot;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; );      &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if (!_metadata.TryResolveResourceType(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; resource[&amp;quot;_ResourceType&amp;quot;].ToString(),       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; out type)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; )      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; throw new InvalidOperationException(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;quot;ResourceType not found&amp;quot;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; );      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return type;      &lt;br /&gt;}&lt;/font&gt;    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;The way we get property values:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;public object GetPropertyValue(     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; object target,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ResourceProperty resourceProperty)      &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; var resource = GetResource(target);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if (resource.ContainsKey(resourceProperty.Name))       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return resource[resourceProperty.Name];      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; throw new InvalidOperationException(&amp;quot;Property not found&amp;quot;);      &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;And finally the way we return query roots. &lt;/p&gt;  &lt;p&gt;If we continue to do what we did in &lt;a href="http://blogs.msdn.com/alexj/archive/2010/01/19/creating-a-data-service-provider-part-5-query.aspx"&gt;part 5&lt;/a&gt;:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;public IQueryable GetQueryRootForResourceSet(     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ResourceSet resourceSet)      &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return _currentDataSource.GetQueryable(resourceSet);      &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;It will work for things URLs like    &lt;br /&gt;&lt;font face="Courier New"&gt;~/Products     &lt;br /&gt;~/Categories&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;But as soon as we do anything interesting like    &lt;br /&gt;    &lt;br /&gt;&lt;font face="Courier New"&gt;~/Products(1)     &lt;br /&gt;~/Products(1)/Category      &lt;br /&gt;~/Categories(1)/Products      &lt;br /&gt;~/Products/?$filter=Name eq 'Marmite'&lt;/font&gt;    &lt;br /&gt;    &lt;br /&gt;It will all fall over in a crashing heap. &lt;/p&gt;  &lt;p&gt;Because we are Un-typed, DataServices will inject calls to &lt;a href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.dataserviceprovidermethods(VS.100).aspx"&gt;DataServiceProviderMethods&lt;/a&gt;.XXX into the query, and then LINQ to Objects will just blindly call those methods – which unfortunately can’t be called directly.&lt;/p&gt;  &lt;p&gt;We need to write a wrapped IQueryable that wraps the LINQ to Objects queryable and rewrites the expression so LINQ to Objects can deal with it.&lt;/p&gt;  &lt;p&gt;Turns out &lt;a href="http://blogs.msdn.com/alexj/archive/2010/03/01/tip-55-how-to-extend-an-iqueryable-by-wrapping-it.aspx"&gt;I wrote a blog post&lt;/a&gt; just yesterday on this :)&lt;/p&gt;  &lt;p&gt;In that blog post I created an &lt;a href="http://blogs.msdn.com/alexj/archive/2010/03/01/tip-55-how-to-extend-an-iqueryable-by-wrapping-it.aspx"&gt;InterceptedQuery&amp;lt;&amp;gt; and InterceptingProvider&lt;/a&gt; that wrap an IQueryable and allow you to visit and alter the expression – which is exactly what we need to do – before it passing it on to the underlying query provider.&lt;/p&gt;  &lt;p&gt;So our method now looks like this:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;public IQueryable GetQueryRootForResourceSet(     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ResourceSet resourceSet)      &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; var underlying = _currentDataSource.GetQueryable(resourceSet);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return &lt;a href="http://blogs.msdn.com/alexj/archive/2010/03/01/tip-55-how-to-extend-an-iqueryable-by-wrapping-it.aspx"&gt;InterceptingProvider.Intercept&lt;/a&gt;(underlying, dspVisitor);&lt;/font&gt;&lt;font face="Courier New"&gt;     &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;h3&gt;Visitor Implementation&lt;/h3&gt;  &lt;p&gt;The interesting piece of course is dspVisitor. This is an instance of a class derived from &lt;a href="http://msdn.microsoft.com/en-us/library/system.linq.expressions.expressionvisitor(VS.100).aspx"&gt;System.Linq.Expressions.ExpressionVisitor&lt;/a&gt; that looks like this:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;public class DSPExpressionVisitor: ExpressionVisitor     &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; static readonly MethodInfo GetValueMethodInfo =       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; typeof(DataServiceProviderMethods)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; .GetMethod(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;quot;GetValue&amp;quot;,      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; BindingFlags.Static | BindingFlags.Public,      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; null,      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; new Type[] {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; typeof(object),       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; typeof(ResourceProperty)&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; },      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; null      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ); &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160; static readonly MethodInfo GetSequenceValueMethodInfo =      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; typeof(DataServiceProviderMethods)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; .GetMethod(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;quot;GetSequenceValue&amp;quot;,      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; BindingFlags.Static | BindingFlags.Public,      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; null,      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; new Type[] {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; typeof(object),       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; typeof(ResourceProperty)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; },      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; null      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ); &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160; static readonly MethodInfo ConvertMethodInfo =      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; typeof(DataServiceProviderMethods)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; .GetMethod(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;quot;Convert&amp;quot;,      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; BindingFlags.Static | BindingFlags.Public      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ); &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160; static readonly MethodInfo TypeIsMethodInfo =&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; typeof(DataServiceProviderMethods)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; .GetMethod(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;quot;TypeIs&amp;quot;,      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; BindingFlags.Static | BindingFlags.Public      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; );&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;// Replace calls to DataServiceProviderMethods.GetValue     &lt;br /&gt;// with this expression.       &lt;br /&gt;// we cast to a dictionary, and then use the dictionary      &lt;br /&gt;// item accessor to get the property.      &lt;br /&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;static readonly Expression&amp;lt;Func&amp;lt;object, ResourceProperty, object&amp;gt;&amp;gt; GetValueReplacement =&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; (o, rp) =&amp;gt; (o as Dictionary&amp;lt;string,object&amp;gt;)[rp.Name];      &lt;br /&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;// To check that something is a particular type we cast to      &lt;br /&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;// Dictionary and compare the _ResourceType field with the     &lt;br /&gt;// fullname of the ResourceType.      &lt;br /&gt;// Obviously this approach won’t handle inheritance.      &lt;br /&gt;static readonly Expression&amp;lt;Func&amp;lt;object, ResourceType, bool&amp;gt;&amp;gt; TypeIsReplacement =       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; (o, rt) =&amp;gt; ((string)(o as Dictionary&amp;lt;string, object&amp;gt;)[&amp;quot;_ResourceType&amp;quot;]) == rt.FullName;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160; protected override Expression VisitMethodCall(     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; MethodCallExpression node      &lt;br /&gt;&amp;#160;&amp;#160; )      &lt;br /&gt;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (node.Method == GetValueMethodInfo)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // Arguments[0] - the resource to get property from      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // Arguments[1] - the ResourceProperty to get      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // Invoke the replacement expression, passing the      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // appropriate parameters.      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return Expression.Invoke(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Expression.Quote(GetValueReplacement),&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; node.Arguments[0],       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; node.Arguments[1]      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; );      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; else if (node.Method.IsGenericMethod &amp;amp;&amp;amp;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; node.Method.GetGenericMethodDefinition() ==&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; GetSequenceValueMethodInfo)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // Arguments[0] - the resource&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // Arguments[1] - the Property that is a sequence&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // Just call the GetValueReplacement(0,1) and      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // cast it to IEnumerable&amp;lt;T&amp;gt; which is the&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // correct return type      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return Expression.Convert(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Expression.Invoke(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Expression.Quote(GetValueReplacement),       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; node.Arguments[0],       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; node.Arguments[1]      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ),      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; node.Method.ReturnType);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; else if (node.Method == TypeIsMethodInfo)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // Arguments[0] – the resource      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // Arguments[1] – the ResourceType      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // Invoke the TypeIsReplacement expression      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // binding to the resource &amp;amp; resourceType      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return Expression.Invoke(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Expression.Quote(TypeIsReplacement),       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; node.Arguments[0],       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; node.Arguments[1]      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; );      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; else if (node.Method == ConvertMethodInfo)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // Arguments[0] – the resource      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // Arguments[0] – the ResourceType      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // no need to do anything, so just      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // return the argument&lt;/font&gt;&lt;font face="Courier New"&gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return this.Visit(node.Arguments[0]);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return base.VisitMethodCall(node);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;This visitor class grabs hold of MethodInfo’s for each of the DataServiceProviderMethods methods, and stores them once for performance reasons.&lt;/p&gt;  &lt;p&gt;Then it overrides VisitMethodCall looking for each of those MethodInfo’s in turn, replacing them with an expression that LINQ to Objects can handle.&lt;/p&gt;  &lt;p&gt;To do this we use a little trick to feed in our replacementExpressions:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;Expression.Invoke(     &lt;br /&gt;&amp;#160;&amp;#160; Expression.Quote(replacementLambda),      &lt;br /&gt;&amp;#160;&amp;#160; argument0,      &lt;br /&gt;&amp;#160;&amp;#160; argument1      &lt;br /&gt;)&lt;/font&gt;    &lt;br /&gt;&amp;#160;&amp;#160; &lt;br /&gt;Using this approach we don’t have to manually construct the lambda expression, which I think makes our visitor easier to read. &lt;/p&gt;  &lt;p&gt;Remember while you are doing this translation / replacement that you need to create expression that your underlying IQueryable provider can actually handle. &lt;/p&gt;  &lt;p&gt;For example LINQ to Objects can handle these expressions without any problem, but the Entity Framework would choke because it &lt;a href="http://blogs.msdn.com/meek/archive/2008/12/07/invocationexpression-and-linq-to-entities.aspx"&gt;can’t translate Invoke Expressions in to SQL&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&lt;font color="#808080"&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; if you using .NET 3.5 – where &lt;/font&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.linq.expressions.expressionvisitor(VS.100).aspx"&gt;&lt;font color="#808080"&gt;System.Linq.Expressions.ExpressionVisitor&lt;/font&gt;&lt;/a&gt;&lt;font color="#808080"&gt; isn’t available – you can still use a visitor derived &lt;/font&gt;&lt;a href="http://iqtoolkit.codeplex.com/"&gt;&lt;font color="#808080"&gt;IQToolkit’s&lt;/font&gt;&lt;/a&gt;&lt;font color="#808080"&gt; base visitor or from &lt;/font&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/bb882521.aspx"&gt;&lt;font color="#808080"&gt;this one&lt;/font&gt;&lt;/a&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/p&gt;  &lt;h3&gt;IDataServiceUpdateProvider Changes:&lt;/h3&gt;  &lt;p&gt;This one is not too tricky: you just need to change each methods so they work against dictionaries rather than strongly typed classes. &lt;/p&gt;  &lt;p&gt;Basically we need to take the &lt;a href="http://blogs.msdn.com/alexj/archive/2010/02/11/creating-a-data-service-provider-part-7-update.aspx"&gt;IDataServiceUpdateProvider implementation in part 7&lt;/a&gt; and update each method in turn to work against a dictionary. &lt;/p&gt;  &lt;p&gt;Generally this actually makes things easier (and faster) because we no longer need to use reflection.&lt;/p&gt;  &lt;p&gt;For example SetValue is a lot easier now:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;public void SetValue(     &lt;br /&gt;&amp;#160;&amp;#160; object targetResource,       &lt;br /&gt;&amp;#160;&amp;#160; string propertyName,       &lt;br /&gt;&amp;#160;&amp;#160; object propertyValue)      &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; try      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; _actions.Add(() =&amp;gt; ReallySetValue(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; targetResource,      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; propertyName,&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; propertyValue)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; );      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; catch { }      &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;public void ReallySetValue(object targetResource, string propertyName, object propertyValue)     &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; var resource = targetResource as Dictionary&amp;lt;string, object&amp;gt;;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; resource[propertyName] = propertyValue;      &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;h3&gt;Putting it altogether&lt;/h3&gt;  &lt;p&gt;If you make all these changes, you should now have a fully functional, Read/Write Un-typed Data Service Provider!&lt;/p&gt;  &lt;p&gt;Congratulations, the world is now officially your oyster…&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9971784" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Expressions/">Expressions</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/LINQ/">LINQ</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/DSP/">DSP</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/IDataServiceQueryProvider/">IDataServiceQueryProvider</category></item><item><title>Tip 55 - How to extend an IQueryable by wrapping it.</title><link>http://blogs.msdn.com/b/alexj/archive/2010/03/01/tip-55-how-to-extend-an-iqueryable-by-wrapping-it.aspx</link><pubDate>Mon, 01 Mar 2010 21:11:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9971098</guid><dc:creator>Alex D James</dc:creator><slash:comments>5</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/alexj/rsscomments.aspx?WeblogPostID=9971098</wfw:commentRss><comments>http://blogs.msdn.com/b/alexj/archive/2010/03/01/tip-55-how-to-extend-an-iqueryable-by-wrapping-it.aspx#comments</comments><description>&lt;P&gt;Over the last couple of years I’ve found myself in lots of situations where I’ve wanted to get ‘under the hood’ and see what is happening inside an IQueryable, but I haven’t had an easy solution, at least until now.&lt;/P&gt;
&lt;P&gt;Getting down and dirty like this is interesting because it means you can:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Log Queries before they are executed &lt;/LI&gt;
&lt;LI&gt;Rewrite expressions, for example replacing expressions that are not supported by a provider - EF, LINQ to SQL, LINQ to Objects etc - with expressions that are. &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Anyway, I was very pleased a while back when reviewing some sample code by Vitek, who has a &lt;A href="http://blogs.msdn.com/vitek/" mce_href="http://blogs.msdn.com/vitek/"&gt;new blog&lt;/A&gt; by the way, and I realized I could generalize it to create an InterceptedQuery&amp;lt;&amp;gt; and an InterceptingProvider.&lt;/P&gt;
&lt;P&gt;The basic idea is that you can use it like this:&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#0000ff face="Courier New"&gt;public IQueryable&amp;lt;Customer&amp;gt; Customers &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp; get{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return InterceptingProvider.CreateQuery(_ctx.Customers, visitor);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tah&gt;Here visitor, is an ExpressionVisitor that will visit, and potentially rewrite, any queries composed with Customers before it is handed off to the underlying queryable (in this case the Entity Framework).&lt;/FONT&gt;&lt;/P&gt;
&lt;H3&gt;Implementation&lt;/H3&gt;
&lt;P&gt;Thanks to Vitek, the implementation is actually pretty simple. &lt;BR&gt;&lt;BR&gt;Lets start with the implementation of the InterceptedQuery&amp;lt;&amp;gt; which is trivial:&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#0000ff face="Courier New"&gt;public class InterceptedQuery&amp;lt;T&amp;gt; : IOrderedQueryable&amp;lt;T&amp;gt; &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private Expression _expression; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private InterceptingProvider _provider; &lt;/FONT&gt;&lt;/P&gt;&lt;PRE&gt;&lt;P&gt;&lt;FONT color=#0000ff face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public InterceptedQuery( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; InterceptingProvider provider, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Expression expression) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this._provider = provider; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this._expression = expression; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IEnumerator&amp;lt;T&amp;gt; GetEnumerator() &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return this._provider.ExecuteQuery&amp;lt;T&amp;gt;(this._expression); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IEnumerator IEnumerable.GetEnumerator() &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return this._provider.ExecuteQuery&amp;lt;T&amp;gt;(this._expression); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Type ElementType &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get { return typeof(T); } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Expression Expression &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get { return this._expression; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IQueryProvider Provider &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get { return this._provider; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;/PRE&gt;
&lt;P&gt;Next lets look at InterceptingProvider which is much more interesting:&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#0000ff face="Courier New"&gt;public class InterceptingProvider : IQueryProvider &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private IQueryProvider _underlyingProvider; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private Func&amp;lt;Expression,Expression&amp;gt;[] _visitors; &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#0000ff face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private InterceptingProvider( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IQueryProvider underlyingQueryProvider, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; params Func&amp;lt;Expression,Expression&amp;gt;[] visitors) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this._underlyingProvider = underlyingQueryProvider; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this._visitors = visitors; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#0000ff face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static IQueryable&amp;lt;T&amp;gt; Intercept&amp;lt;T&amp;gt;( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IQueryable&amp;lt;T&amp;gt; underlyingQuery, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; params ExpressionVisitor[] visitors) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Func&amp;lt;Expression, Expression&amp;gt;[] visitFuncs = &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; visitors &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Select(v =&amp;gt; (Func&amp;lt;Expression, Expression&amp;gt;) v.Visit) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .ToArray(); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return Intercept&amp;lt;T&amp;gt;(underlyingQuery, visitFuncs); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#0000ff face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static IQueryable&amp;lt;T&amp;gt; Intercept&amp;lt;T&amp;gt;( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IQueryable&amp;lt;T&amp;gt; underlyingQuery, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; params Func&amp;lt;Expression,Expression&amp;gt;[] visitors) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; InterceptingProvider provider = new InterceptingProvider( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; underlyingQuery.Provider, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; visitors &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return provider.CreateQuery&amp;lt;T&amp;gt;( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; underlyingQuery.Expression); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IEnumerator&amp;lt;TElement&amp;gt; ExecuteQuery&amp;lt;TElement&amp;gt;( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Expression expression) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return _underlyingProvider.CreateQuery&amp;lt;TElement&amp;gt;( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; InterceptExpr(expression) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ).GetEnumerator(); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IQueryable&amp;lt;TElement&amp;gt; CreateQuery&amp;lt;TElement&amp;gt;( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Expression expression) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return new InterceptedQuery&amp;lt;TElement&amp;gt;(this, expression); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IQueryable CreateQuery(Expression expression) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Type et = TypeHelper.FindIEnumerable(expression.Type); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Type qt = typeof(InterceptedQuery&amp;lt;&amp;gt;).MakeGenericType(et); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; object[] args = new object[] { this, expression }; &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#0000ff face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ConstructorInfo ci = qt.GetConstructor( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; BindingFlags.NonPublic | BindingFlags.Instance, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; null, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new Type[] {&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; typeof(InterceptingProvider), &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; typeof(Expression) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; null); &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#0000ff face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return (IQueryable)ci.Invoke(args); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public TResult Execute&amp;lt;TResult&amp;gt;(Expression expression) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return this._underlyingProvider.Execute&amp;lt;TResult&amp;gt;( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; InterceptExpr(expression) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public object Execute(Expression expression) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return this._underlyingProvider.Execute( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; InterceptExpr(expression) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private Expression InterceptExpr(Expression expression) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Expression exp = expression; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach (var visitor in _visitors) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; exp = visitor(exp); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return exp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Notice that whenever the Query is executed, we Intercept the current Expression, which involves calling all registered ‘visitors’ in turn, and then executing the resulting expression against the underlying provider.&lt;/P&gt;
&lt;H3&gt;Implementation Notes:&lt;/H3&gt;
&lt;P&gt;At its foundation our implementation uses Func&amp;lt;Expression,Expression&amp;gt; rather than .NET 4.0’s &lt;A href="http://msdn.microsoft.com/en-us/library/system.linq.expressions.expressionvisitor(VS.100).aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.linq.expressions.expressionvisitor(VS.100).aspx"&gt;System.Linq.Expressions.ExpressionVisitor&lt;/A&gt;, mainly because .NET was a little late to the party, so there are lots of visitors that don’t derive from &lt;A href="http://msdn.microsoft.com/en-us/library/system.linq.expressions.expressionvisitor(VS.100).aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.linq.expressions.expressionvisitor(VS.100).aspx"&gt;System.Linq.Expressions.ExpressionVisitor&lt;/A&gt; today. &lt;BR&gt;&lt;BR&gt;You need look no further than Matt Warren’s excellent &lt;A href="http://bit.ly/d81aKS" mce_href="http://bit.ly/d81aKS"&gt;IQToolkit&lt;/A&gt;, for many such examples.&lt;/P&gt;
&lt;P&gt;Nevertheless we want to encourage the use of &lt;A href="http://msdn.microsoft.com/en-us/library/system.linq.expressions.expressionvisitor(VS.100).aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.linq.expressions.expressionvisitor(VS.100).aspx"&gt;System.Linq.Expressions.ExpressionVisitor&lt;/A&gt; so there is a convenience overload for that too.&lt;/P&gt;
&lt;P&gt;Remember also that if you are wrapping the Entity Framework and doing any non-trivial expression rewrites you have to avoid any Invoke Expressions - see &lt;A href="http://bit.ly/8Zvtlf" mce_href="http://bit.ly/8Zvtlf"&gt;&lt;FONT color=#000000&gt;Colin’s blog post&lt;/FONT&gt;&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;One of &lt;A href="http://bit.ly/d81aKS" mce_href="http://bit.ly/d81aKS"&gt;IQToolkit&lt;/A&gt; useful visitors is called ExpressionWriter and with a few minor mods – making both its constructor and the base Visit method public – you can use it to write the expression to the console before any Entity Framework query is executed:&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#0000ff face="Courier New"&gt;CustomersContext _ctx = new CustomersContext(); &lt;BR&gt;ExpressionWriter _writer = new ExpressionWriter(Console.Out); &lt;BR&gt;&lt;BR&gt;public IQueryable&amp;lt;Customer&amp;gt; Customers{ &lt;BR&gt;&amp;nbsp;&amp;nbsp; get{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return InterceptingProvider.Intercept(_ctx.Customers, _writer.Visit); &lt;BR&gt;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;}&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;You’ll also notice that we are using the &lt;A href="http://bit.ly/d81aKS" mce_href="http://bit.ly/d81aKS"&gt;IQToolkit’s&lt;/A&gt; useful TypeHelper class in our untyped CreateQuery method, it really helps us create the correct generic InterceptedQuery&amp;lt;&amp;gt; instance. &lt;/P&gt;
&lt;P&gt;Thanks again Matt!&lt;/P&gt;
&lt;H3&gt;Putting it all together:&lt;/H3&gt;
&lt;P&gt;Lets show an end to end example. &lt;/P&gt;
&lt;P&gt;Here I mimic what a WCF/ADO.NET Data Service has to do to handle this request:&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#0000ff face="Courier New"&gt;GET ~/People/?$filter=Surname eq ‘James’&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;if it is backed by an un-typed DSP.&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#008000&gt;// Create some data&lt;/FONT&gt; &lt;BR&gt;&lt;FONT color=#0000ff&gt;List&amp;lt;Dictionary&amp;lt;string, object&amp;gt;&amp;gt; data = new List&amp;lt;Dictionary&amp;lt;string, object&amp;gt;&amp;gt;(); &lt;BR&gt;data.Add( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new Dictionary&amp;lt;string, object&amp;gt;{{"Surname", "James"}, {"Firstname", "Alex"}} &lt;BR&gt;); &lt;BR&gt;data.Add( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new Dictionary&amp;lt;string, object&amp;gt;{{"Surname", "&lt;/FONT&gt;&lt;/FONT&gt;&lt;A href="http://damieng.com/" mce_href="http://damieng.com/"&gt;&lt;FONT color=#0000ff face="Courier New"&gt;Guard&lt;/FONT&gt;&lt;/A&gt;&lt;FONT color=#0000ff face="Courier New"&gt;"}, {"Firstname", "Damien"}} &lt;BR&gt;); &lt;BR&gt;data.Add( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new Dictionary&amp;lt;string, object&amp;gt;{{"Surname", "&lt;/FONT&gt;&lt;A href="http://blogs.msdn.com/meek" mce_href="http://blogs.msdn.com/meek"&gt;&lt;FONT color=#0000ff face="Courier New"&gt;Meek&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff&gt;"}, {"Firstname", "Colin"}} &lt;BR&gt;); &lt;BR&gt;data.Add( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new Dictionary&amp;lt;string, object&amp;gt;{{"Surname", "&lt;/FONT&gt;&lt;A href="http://blogs.msdn.com/vitek" mce_href="http://blogs.msdn.com/vitek"&gt;&lt;FONT color=#0000ff&gt;Karas&lt;/FONT&gt;&lt;/A&gt;&lt;FONT color=#0000ff&gt;"}, {"Firstname", "Vitek"}}&lt;/FONT&gt;&lt;/FONT&gt; &lt;BR&gt;&lt;FONT color=#0000ff&gt;); &lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff face="Courier New"&gt;data.Add( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new Dictionary&amp;lt;string, object&amp;gt;{{"Surname", "&lt;/FONT&gt;&lt;A href="http://blogs.msdn.com/mattwar" mce_href="http://blogs.msdn.com/mattwar"&gt;&lt;FONT color=#0000ff face="Courier New"&gt;Warren&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff&gt;"}, {"Firstname", "Matt"}} &lt;BR&gt;);&lt;/FONT&gt; &lt;BR&gt;&lt;BR&gt;&lt;FONT color=#008000&gt;// Create a couple of visitors &lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff face="Courier New"&gt;var writer = new ExpressionWriter(Console.Out); &lt;BR&gt;var dspVisitor = new DSPExpressionVisitor();&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#008000&gt;// Intercept queries to the L2O IQueryable&lt;/FONT&gt; &lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff&gt;var queryRoot = InterceptingProvider.Intercept( &lt;BR&gt;&amp;nbsp;&amp;nbsp; data.AsQueryable(), &lt;FONT color=#008000&gt;// L2O’s iqueryable&lt;/FONT&gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp; writer.Visit, &lt;FONT color=#008000&gt;// What does the expression look like first? &lt;BR&gt;&lt;/FONT&gt;&amp;nbsp;&amp;nbsp; dspVisitor.Visit, &lt;FONT color=#008000&gt;// Replace GetValue().&lt;/FONT&gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp; writer.Visit &lt;FONT color=#008000&gt;// What does the expression look like now?&lt;/FONT&gt; &lt;BR&gt;);&lt;/FONT&gt; &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#008000&gt;// Create a Data Services handle for the Surname property&lt;/FONT&gt; &lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff face="Courier New"&gt;ResourceProperty surname = new ResourceProperty( &lt;BR&gt;&amp;nbsp;&amp;nbsp; "Surname", &lt;BR&gt;&amp;nbsp;&amp;nbsp; ResourcePropertyKind.Primitive, &lt;BR&gt;&amp;nbsp;&amp;nbsp; ResourceType.GetPrimitiveResourceType(typeof(string)) &lt;BR&gt;);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#008000&gt;// Create a query without knowing how to access the Surname &lt;BR&gt;// from x.&lt;/FONT&gt; &lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff&gt;var query = &lt;BR&gt;&amp;nbsp; from x in queryRoot &lt;BR&gt;&amp;nbsp; where ((string) &lt;/FONT&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.dataserviceprovidermethods.getvalue(VS.100).aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.dataserviceprovidermethods.getvalue(VS.100).aspx"&gt;&lt;FONT color=#0000ff&gt;DataServiceProviderMethods.GetValue&lt;/FONT&gt;&lt;/A&gt;&lt;FONT color=#0000ff&gt;(x, surname)) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; == "James" &lt;BR&gt;&amp;nbsp; select x;&lt;/FONT&gt; &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#008000&gt;// Execute the query and print some results&lt;/FONT&gt; &lt;BR&gt;&lt;FONT color=#0000ff&gt;foreach (var x in query) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("Found Match:{0}", &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; x["Firstname"].ToString() &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; );&lt;/FONT&gt; &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;BR&gt;As can see we have some People data in a list of dictionaries, and we are trying to find just the People with a Surname of ‘James’. &lt;/P&gt;
&lt;P&gt;The problem is that Data Services doesn’t know how to get the Surname from a Dictionary. So it injects a call to &lt;A href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.dataserviceprovidermethods.getvalue(VS.100).aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.dataserviceprovidermethods.getvalue(VS.100).aspx"&gt;DataServiceProviderMethods.GetValue(..)&lt;/A&gt;. &lt;/P&gt;
&lt;P&gt;Fine.&lt;/P&gt;
&lt;P&gt;Unfortunately at this point the LINQ to Objects query provider doesn’t have enough context to process this query - blindly calling GetValue like we are doing in this query will fail.&lt;/P&gt;
&lt;P&gt;So we intercept the query, and the DSPExpressionVisitor (which I won’t go into here) simply replaces things like this:&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#0000ff face="Courier New"&gt;DataServiceProviderMethods.GetValue(x, surname)&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;with this&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#0000ff face="Courier New"&gt;x[surname.Name]&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;which if you look at surname you can see is the same as:&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#0000ff face="Courier New"&gt;x["Surname"]&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;So when the whole expression is visited you end up with something like this:&lt;/P&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff&gt;var query =&amp;nbsp; &lt;BR&gt;&amp;nbsp; from x in queryRoot &lt;BR&gt;&amp;nbsp; where ((string) x[surname.Name]) == "James" &lt;BR&gt;&amp;nbsp; select x;&lt;/FONT&gt; &lt;/FONT&gt;
&lt;P&gt;Which Linq to Objects can handle just fine!&lt;/P&gt;
&lt;H3&gt;Summary&lt;/H3&gt;
&lt;P&gt;This is a general purpose solution that allows you to layer one IQueryable over another, and translate / rewrite / log the query expression before it is passed to the underlying provider.&lt;/P&gt;
&lt;P&gt;Enjoy.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9971098" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/alexj/archive/tags/C_2300_/">C#</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Expressions/">Expressions</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Tips/">Tips</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Entity+Framework/">Entity Framework</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Data+Services/">Data Services</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/IDataServiceQueryProvider/">IDataServiceQueryProvider</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/IQueryable/">IQueryable</category></item><item><title>Creating a Data Service Provider – Part 8 - Relationships</title><link>http://blogs.msdn.com/b/alexj/archive/2010/02/24/creating-a-data-service-provider-part-8-relationships.aspx</link><pubDate>Wed, 24 Feb 2010 02:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9968431</guid><dc:creator>Alex D James</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/alexj/rsscomments.aspx?WeblogPostID=9968431</wfw:commentRss><comments>http://blogs.msdn.com/b/alexj/archive/2010/02/24/creating-a-data-service-provider-part-8-relationships.aspx#comments</comments><description>&lt;p&gt;In &lt;a href="http://blogs.msdn.com/alexj/archive/2010/01/07/data-service-providers-getting-started.aspx" mce_href="http://blogs.msdn.com/alexj/archive/2010/01/07/data-service-providers-getting-started.aspx"&gt;parts 1 thru 7&lt;/a&gt; we made a Read / Write typed data service provider, although it was a little simplistic because it didn’t have relationships. &lt;/p&gt;  &lt;p&gt;So lets rectify that right now by adding a relationship to make this more 'real-world' &lt;br&gt;&lt;/p&gt;  &lt;h3&gt;Changes to our Classes&lt;/h3&gt;  &lt;p&gt;If you remember from &lt;a href="http://blogs.msdn.com/alexj/archive/2010/01/08/creating-a-data-service-provider-part-3-metadata.aspx" mce_href="http://blogs.msdn.com/alexj/archive/2010/01/08/creating-a-data-service-provider-part-3-metadata.aspx"&gt;Part 3&lt;/a&gt; we had just a Product class, so lets add a Category and a one to many relationship between the two:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;public class Category      &lt;br&gt;{       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private List&amp;lt;Product&amp;gt; _products = new List&amp;lt;Product&amp;gt;(); &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public int ID { get; set; }      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string Name { get; set; }       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public List&amp;lt;Product&amp;gt; Products { get { return _products; } }       &lt;br&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;public class Product      &lt;br&gt;{       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public int ProdKey { get; set; }       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string Name { get; set; }       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Decimal Price { get; set; }       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Decimal Cost { get; set; }       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Category Category { get; set; }       &lt;br&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;h3&gt;Metadata Changes&lt;/h3&gt;  &lt;h4&gt;Building relationships through metadata.&lt;/h4&gt;  &lt;p&gt;Now that our classes are ready, the next step is to tell Data Services about Category, and the relationships between then two classes:&lt;/p&gt;  &lt;p&gt;Most of this is simple, except perhaps the bit that actually adds the relationship.    &lt;br&gt;    &lt;br&gt;You start by creating the ‘navigation’ properties: &lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;var productType = …; // Product and its primitive properties      &lt;br&gt;var categoryType = …; // Category and its primitive properties&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;// Tell Data Services about product.Category      &lt;br&gt;var prodCategory = new ResourceProperty(       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Category",       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ResourcePropertyKind.ResourceReference,       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; categoryType       &lt;br&gt;);       &lt;br&gt;productType.AddProperty(prodCategory);&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;// Tell Data Services about category.Products      &lt;br&gt;var catProducts = new ResourceProperty(       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Products",       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ResourcePropertyKind.ResourceSetReference,       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; productType       &lt;br&gt;);       &lt;br&gt;categoryType.AddProperty(catProducts);&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Because of the way the API works – you need the target ResourceType to create a property – both Resource Types need to be at least partially created before you can create and add the navigation properties. &lt;/p&gt;  &lt;p&gt;This essentially means you need to do two passes over each ResourceType: One to create the type and its primitive properties and another to add it’s navigation properties.&lt;/p&gt;  &lt;p&gt;You should also notice that product.Category is a ResourceReference, because there is just one category, whereas category.Products is a ResourceSetReference, because it is a collection.&lt;/p&gt;  &lt;p&gt;Next we need a ResourceSet for both Category and Product: &lt;/p&gt; &lt;font face="Courier New"&gt;var productsSet = new ResourceSet("Products", productType);    &lt;br&gt;var categoriesSet = new ResourceSet("Categories", categoryType);&lt;/font&gt;   &lt;p&gt;Once you done that we need to create an AssociationSet that links those two navigation properties and resource sets together:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;ResourceAssociationSet productCategoryAssociationSet = new ResourceAssociationSet(      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "ProductCategory",       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new ResourceAssociationSetEnd(       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; productsSet,       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; productType,&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; prodCategory       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ),       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new ResourceAssociationSetEnd(       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; categoriesSet,       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; categoryType,&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; catProducts       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; )       &lt;br&gt;);&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;i.e. this is the bit that tells Data Services that setting:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;product.Category = category;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;is equivalent to:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;category.Products.Add(product);&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Next we store a pointer from these properties back to the ResourceAssociationSet using the CustomState property.&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;prodCategory.CustomState = productCategoryAssociationSet;      &lt;br&gt;catProducts.CustomState = productCategoryAssociationSet;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;If you remember the good old days of VB forms development CustomState will remind you of your old friend the Tag property. You can use it for all sorts of tricks.&lt;/p&gt;  &lt;p&gt;Actually storing the ResourceAssociationSet in the ResourceProperty.CustomState is not strictly necessary, but it will make our lives easier, and our code quicker, as you’ll see very soon.&lt;/p&gt;  &lt;p&gt;Finally we need to tell the DSPMetadataProvider, about both ResourceTypes, both ResourceSets and the ResourceAssociationSet:    &lt;br&gt;    &lt;br&gt;&lt;font face="Courier New"&gt;metadata.AddResourceType(productType);      &lt;br&gt;metadata.AddResourceSet(productsSet);       &lt;br&gt;metadata.AddResourceType(categoryType);       &lt;br&gt;metadata.AddResourceSet(categoriesSet);       &lt;br&gt;metadata.AddAssociationSet(productCategoryAssociationSet);&lt;/font&gt;&lt;/p&gt;  &lt;h4&gt;IDataServiceMetadataProvider Changes&lt;/h4&gt;  &lt;p&gt;For this to work we need to make some changes to our DSPMetadataProvider to actually support Relationships:&lt;/p&gt;  &lt;p&gt;First we need a place to hold AssociationSets:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;List&amp;lt;ResourceAssociationSet&amp;gt; _associationSets&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp; = new List&amp;lt;ResourceAssociationSet&amp;gt;();       &lt;br&gt;      &lt;br&gt;&lt;/font&gt;&lt;font face="Tah"&gt;Then we need a way to register new AssociationsSets:&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;public void AddAssociationSet(ResourceAssociationSet aset)      &lt;br&gt;{       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _associationSets.Add(aset);       &lt;br&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;And finally we need to update our implementation of IDataServiceMetadataProvider.GetResourceAssociationSet(..) like this:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;public virtual ResourceAssociationSet GetResourceAssociationSet(      &lt;br&gt;&amp;nbsp;&amp;nbsp; ResourceSet resourceSet,       &lt;br&gt;&amp;nbsp;&amp;nbsp; ResourceType resourceType,       &lt;br&gt;&amp;nbsp;&amp;nbsp; ResourceProperty resourceProperty       &lt;br&gt;)       &lt;br&gt;{       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return resourceProperty.CustomState as ResourceAssociationSet       &lt;br&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;See I told you putting the ResourceAssociationSet in CustomState was going to come in handy!    &lt;br&gt;    &lt;br&gt;The alternative is to write a LINQ query over the _associationSets list, using the method arguments in the predicate, but that is a little more complicated and a lot slower.&lt;/p&gt;  &lt;h4&gt;Metadata should be working by now…&lt;/h4&gt;  &lt;p&gt;By this point both the service document: &lt;b&gt;~/Sample.svc&lt;/b&gt; and metadata: &lt;b&gt;~/Sample.svc/$metadata&lt;/b&gt; should be working.&lt;/p&gt;  &lt;p&gt;Next we move on to getting query and update working, and to do that we so we need to update our Data Source, and our implementation of IDataServiceQueryProvider.&lt;/p&gt;&lt;h3&gt;Query Changes&lt;/h3&gt;  &lt;h4&gt;Updating our DataSource&lt;/h4&gt;  &lt;p&gt;This just involves adding a List for my categories to ProductsContext, and updating the existing methods to expose Categories too:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;public class ProductsContext: DSPContext      &lt;br&gt;{       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static List&amp;lt;Product&amp;gt; _products&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = new List&amp;lt;Product&amp;gt;();       &lt;br&gt;      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static List&amp;lt;Category&amp;gt; _categories       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = new List&amp;lt;Category&amp;gt;(); &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public override IQueryable GetQueryable(      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ResourceSet resourceSet)       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (resourceSet.Name == "Products")       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return Products.AsQueryable();       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else if (resourceSet.Name == "Categories")       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return Categories.AsQueryable(); &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new NotSupportedException(      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string.Format("{0} not found", resourceSet.Name));       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }       &lt;br&gt;      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static List&amp;lt;Product&amp;gt; Products{       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get { return _products; }       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }       &lt;br&gt;      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static List&amp;lt;Category&amp;gt; Categories {       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get { return _categories; }       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }       &lt;br&gt;      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public override void AddResource(       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ResourceType resourceType, object resource)       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (resourceType.InstanceType == typeof(Product))       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Product p = resource as Product;       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (p != null)       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Products.Add(p);       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return;       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else if (resourceType.InstanceType == typeof(Category))       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Category c = resource as Category;       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (c != null)       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Categories.Add(c);       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return;       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new NotSupportedException(       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string.Format("{0} not found", resourceType.FullName));       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }       &lt;br&gt;      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public override void DeleteResource(object resource)       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (resource.GetType() == typeof(Product))       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Products.Remove(resource as Product);       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return;       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else if (resource.GetType() == typeof(Category))       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Categories.Remove(resource as Category);       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return;       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new NotSupportedException("Resource Not Found");       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }       &lt;br&gt;      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public override object CreateResource(       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ResourceType resourceType)       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (resourceType.InstanceType == typeof(Product))       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return new Product();       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else if (resourceType.InstanceType == typeof(Category))       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return new Category();       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new NotSupportedException(       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string.Format("{0} not found", resourceType.FullName));       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }       &lt;br&gt;      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public override void SaveChanges()       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var prodKey = Products.Max(p =&amp;gt; p.ProdKey);       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach (var prod in Products.Where(p =&amp;gt; p.ProdKey == 0))       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; prod.ProdKey = ++prodKey; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var catKey = Categories.Max(p =&amp;gt; p.ID);      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach (var cat in Categories.Where(c =&amp;gt; c.ID == 0))       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cat.ID = ++catKey;       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }       &lt;br&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;As you can see this is mostly just a mechanical modification of the code we already had for Products. If I was doing this for real, I’d be looking are refactoring this code, to make adding another type a more pain free.    &lt;br&gt;    &lt;br&gt;But I’ll leave that as an exercise for you guys.&lt;/p&gt;  &lt;p&gt;The only thing remaining to get query working is to actually have some data:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;protected override ProductsContext&amp;nbsp; CreateDataSource()      &lt;br&gt;{       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (ProductsContext.Products.Count == 0)       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var bovril = new Product       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ProdKey = 1,       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Name = "Bovril",       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Cost = 4.35M,       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Price = 6.49M       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; };       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var marmite = new Product       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ProdKey = 2,       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Name = "Marmite",       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Cost = 4.97M,       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Price = 7.21M       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; };       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var food = new Category       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ID = 1,       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Name = "Food"       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; };       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; food.Products.Add(bovril);       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; bovril.Category = food;       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; food.Products.Add(marmite);       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; marmite.Category = food;       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ProductsContext.Categories.Add(food);       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ProductsContext.Products.Add(bovril);       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ProductsContext.Products.Add(marmite);       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return base.CreateDataSource();       &lt;br&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Notice that I am building the relationships in both directions, sometimes this logic might be built into the classes themselves – it is what the Entity Framework calls relationship fix-up – if so this would be superfluous.&lt;/p&gt;  &lt;p&gt;Either way if you try running your code at this point you should be able to get both query AND relationship traversal working.&lt;/p&gt;  &lt;p&gt;i.e. getting the Category for a particular Product:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/CreatingaDataServiceProviderPart8Relatio_DE62/RelationshipTraversal.png" mce_href="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/CreatingaDataServiceProviderPart8Relatio_DE62/RelationshipTraversal.png"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/CreatingaDataServiceProviderPart8Relatio_DE62/RelationshipTraversal_thumb.png" style="border-width: 0px; display: inline;" title="RelationshipTraversal" alt="RelationshipTraversal" mce_src="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/CreatingaDataServiceProviderPart8Relatio_DE62/RelationshipTraversal_thumb.png" border="0" width="644" height="179"&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;and getting the Products in a particular Category:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/CreatingaDataServiceProviderPart8Relatio_DE62/RelationshipTraversal2.png" mce_href="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/CreatingaDataServiceProviderPart8Relatio_DE62/RelationshipTraversal2.png"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/CreatingaDataServiceProviderPart8Relatio_DE62/RelationshipTraversal2_thumb.png" style="border-width: 0px; display: inline;" title="RelationshipTraversal2" alt="RelationshipTraversal2" mce_src="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/CreatingaDataServiceProviderPart8Relatio_DE62/RelationshipTraversal2_thumb.png" border="0" width="644" height="360"&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Its also interesting to notice that we didn’t need to make any changes to our implementation of IDataServiceQueryProvider to get Query working.&lt;br&gt;&lt;/p&gt;  &lt;h3&gt;Update Changes&lt;/h3&gt;  &lt;p&gt;Our last challenge is getting Update working.&lt;/p&gt;  &lt;p&gt;Which basically means implementing these three methods that we didn’t need &lt;a href="http://blogs.msdn.com/alexj/archive/2010/02/11/creating-a-data-service-provider-part-7-update.aspx" mce_href="http://blogs.msdn.com/alexj/archive/2010/02/11/creating-a-data-service-provider-part-7-update.aspx"&gt;last time&lt;/a&gt;:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;public void SetReference(      &lt;br&gt;&amp;nbsp;&amp;nbsp; object targetResource,       &lt;br&gt;&amp;nbsp;&amp;nbsp; string propertyName,       &lt;br&gt;&amp;nbsp;&amp;nbsp; object propertyValue)       &lt;br&gt;{       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new NotImplementedException();       &lt;br&gt;}       &lt;br&gt;public void AddReferenceToCollection(       &lt;br&gt;&amp;nbsp;&amp;nbsp; object targetResource,       &lt;br&gt;&amp;nbsp;&amp;nbsp; string propertyName,       &lt;br&gt;&amp;nbsp;&amp;nbsp; object resourceToBeAdded)       &lt;br&gt;{       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new NotImplementedException();       &lt;br&gt;}       &lt;br&gt;public void RemoveReferenceFromCollection(       &lt;br&gt;&amp;nbsp;&amp;nbsp; object targetResource,       &lt;br&gt;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font face="Courier New"&gt;string propertyName,      &lt;br&gt;&amp;nbsp;&amp;nbsp; object resourceToBeRemoved)       &lt;br&gt;{       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new NotImplementedException();       &lt;br&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Remember (from &lt;a href="http://blogs.msdn.com/alexj/archive/2010/02/11/creating-a-data-service-provider-part-7-update.aspx" mce_href="http://blogs.msdn.com/alexj/archive/2010/02/11/creating-a-data-service-provider-part-7-update.aspx"&gt;part 7&lt;/a&gt;) that our Update Providers need to delay doing updates until IDataServiceUpdateProvider.SaveChanges() is called, so we record our intent to SetReference as an action.&lt;/p&gt;  &lt;p&gt;To make this easy we’ll create methods that do the real work and call theme inside actions we can invoke later:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;public void SetReference(     &lt;br&gt;&amp;nbsp;&amp;nbsp; object targetResource,       &lt;br&gt;&amp;nbsp;&amp;nbsp; string propertyName,       &lt;br&gt;&amp;nbsp;&amp;nbsp; object propertyValue)      &lt;br&gt;{      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _actions.Add(() =&amp;gt; ReallySetReference(      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; targetResource,       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; propertyName,&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; propertyValue));      &lt;br&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;     &lt;br&gt;public void AddReferenceToCollection(      &lt;br&gt;&amp;nbsp;&amp;nbsp; object targetResource,       &lt;br&gt;&amp;nbsp;&amp;nbsp; string propertyName,       &lt;br&gt;&amp;nbsp;&amp;nbsp; object resourceToBeAdded)      &lt;br&gt;{      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _actions.Add(() =&amp;gt; ReallyAddReferenceToCollection(      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; targetResource,      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; propertyName,      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; resourceToBeAdded));      &lt;br&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;public void RemoveReferenceFromCollection(     &lt;br&gt;&amp;nbsp;&amp;nbsp; object targetResource,       &lt;br&gt;&amp;nbsp;&amp;nbsp; string propertyName,       &lt;br&gt;&amp;nbsp;&amp;nbsp; object resourceToBeRemoved)      &lt;br&gt;{      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _actions.Add(() =&amp;gt; ReallyRemoveReferenceFromCollection(      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; targetResource,      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; propertyName,      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; resourceToBeRemoved));      &lt;br&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;So what do those ReallyXXX() methods look like?&lt;/p&gt;&lt;p&gt; Well something to bear in mind here is that our classes are pretty naive – they don’t do any relationship fix-up – yet the relationships themselves are bi-directional, so our code needs to keep both ends of the relationship in sync. &lt;/p&gt;&lt;p&gt;This is what ReallySetReference(..) looks like: &lt;br&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;public void ReallySetReference(     &lt;br&gt;&amp;nbsp;&amp;nbsp; object targetResource,       &lt;br&gt;&amp;nbsp;&amp;nbsp; string propertyName,       &lt;br&gt;&amp;nbsp;&amp;nbsp; object propertyValue)      &lt;br&gt;{      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Get the resource type.      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var targetType = targetResource.GetType();      &lt;br&gt;      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Figure out the other end...      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var targetResourceType =       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _metadata.Types.Single(t =&amp;gt; t.InstanceType==targetType);      &lt;br&gt;      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var targetResourceTypeProperty = targetResourceType      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Properties      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Single(p =&amp;gt; p.Name == propertyName);      &lt;br&gt;      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var associationSet = targetResourceTypeProperty      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font face="Courier New"&gt;.CustomState as ResourceAssociationSet     &lt;br&gt;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Get the relatedEnd      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var relatedAssociationSetEnd = associationSet.End1      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .ResourceProperty == targetResourceTypeProperty ?&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font face="Courier New"&gt;associationSet.End2 : associationSet.End1;     &lt;br&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;     &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var relatedResourceTypeProperty = relatedAssociationSetEnd      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .ResourceProperty; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Get the relatedType and all Properties     &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Type relatedType = relatedAssociationSetEnd      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .ResourceType      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .InstanceType;      &lt;br&gt;      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var targetTypeProperty = targetType      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .GetProperties()      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Single(p =&amp;gt; p.Name == propertyName);      &lt;br&gt;      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var relatedTypeProperty =&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; relatedResourceTypeProperty == null ?       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; null :       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; relatedType.GetProperties()      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Single(p =&amp;gt; p.Name == relatedResourceTypeProperty.Name); &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // We need to fix up the other end     &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // but&lt;/font&gt;&lt;font face="Courier New"&gt; only if this is a two way relationship     &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (relatedResourceTypeProperty != null)      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Get the other end and clears its       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // relationship to targetResource      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; object originalValue = targetTypeProperty      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .GetPropertyValueFromTarget(targetResource);      &lt;br&gt;      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (originalValue != null)      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (relatedAssociationSetEnd.ResourceProperty.Kind ==       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ResourcePropertyKind.ResourceReference)      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // the other end is a reference so we check       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // &lt;/font&gt;&lt;font face="Courier New"&gt;that it is pointing to the targetResource     &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // before nulling out.      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var backPointer =      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; relatedTypeProperty      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .GetPropertyValueFromTarget(originalValue);      &lt;br&gt;      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (object.ReferenceEquals(      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; backPointer,&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; targetResource)      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; )       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; relatedTypeProperty.SetPropertyValueOnTarget(      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; originalValue, null);      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else if (relatedAssociationSetEnd      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .ResourceProperty.Kind ==&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ResourcePropertyKind.ResourceSetReference)      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // the other end is a collection       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // (i.e. a List in our implementation) so we can       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // safely remove targetResource without checking      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // whether it is in that list or not      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (relatedTypeProperty      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font face="Courier New"&gt;.GetPropertyValueFromTarget(originalValue)      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; as IList      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ).Remove(targetResource);      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Add the relationship to the other end...      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (propertyValue != null)      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (relatedAssociationSetEnd.ResourceProperty.Kind ==&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ResourcePropertyKind.ResourceReference)      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; relatedTypeProperty.SetPropertyValueOnTarget(      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; propertyValue, targetResource);      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else if (relatedAssociationSetEnd      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .ResourceProperty.Kind ==       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ResourcePropertyKind.ResourceSetReference)      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (relatedTypeProperty      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .GetPropertyValueFromTarget(propertyValue)&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; as IList      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ).Add(targetResource);      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // actually set the reference !      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; targetTypeProperty.SetPropertyValueOnTarget(      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; targetResource, propertyValue      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; );      &lt;br&gt;} &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;As you can see this is pretty complicated, but if you look closely you'll notice most of the complexity comes from the fix-up logic. Indeed if the Product and Category classes did their own fix-up logic this would suffice:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;public void ReallySetReference(     &lt;br&gt;&amp;nbsp;&amp;nbsp; object targetResource,       &lt;br&gt;&amp;nbsp;&amp;nbsp; string propertyName,       &lt;br&gt;&amp;nbsp;&amp;nbsp; object propertyValue)      &lt;br&gt;{      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Get the resource type.      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var targetType = targetResource.GetType();&lt;/font&gt;&lt;font face="Courier New"&gt;     &lt;br&gt;      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var targetTypeProperty = targetType      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .GetProperties()      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Single(p =&amp;gt; p.Name == propertyName);      &lt;br&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;     &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // actually set the reference !      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; targetTypeProperty.SetPropertyValueOnTarget(      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; targetResource, propertyValue      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; );      &lt;br&gt;} &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;As you can see that is much better, so if you know the classes your DSP exposes do their own fixup remember to take advantage of that.&lt;/p&gt;  &lt;p&gt;In the above code I’m also using a couple of extension methods to make this code ‘easier’ (a relative term) to read:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;public static void SetPropertyValueOnTarget(     &lt;br&gt;&amp;nbsp;&amp;nbsp; this PropertyInfo property,&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp; object target,       &lt;br&gt;&amp;nbsp;&amp;nbsp; object value)      &lt;br&gt;{      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; property.GetSetMethod()      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Invoke(target,new object[] { value });      &lt;br&gt;}      &lt;br&gt;public static object GetPropertyValueFromTarget(      &lt;br&gt;&amp;nbsp;&amp;nbsp; this PropertyInfo property,       &lt;br&gt;&amp;nbsp;&amp;nbsp; object target)      &lt;br&gt;{      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return property.GetGetMethod()      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Invoke(target, new object[] { });      &lt;br&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;The next step is implementing both ReallyRemoveReferenceFromCollection(..) and ReallyAddReferenceToCollection(..). &lt;br&gt;&lt;br&gt;But I’ll leave that to you the astute reader, because it is more about implementing fixup than implementing a DSP at this point.&lt;/p&gt;  &lt;p&gt;When you’ve got all those methods implemented you should have a working &lt;b&gt;&lt;u&gt;Strongly Typed Read/Write Data Service with Relationships&lt;/u&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;So congratulations are in order!!&lt;br&gt;&lt;/p&gt;  &lt;p&gt;Next up we’ll look at doing this all over again, this time un-typed.    &lt;br&gt;    &lt;br&gt;Along the way you are going to learn some nifty IQueryable tricks :)&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9968431" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Entity+Framework/">Entity Framework</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Data+Services/">Data Services</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Fixup/">Fixup</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/DSP/">DSP</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/IDataServiceMetadataProvider/">IDataServiceMetadataProvider</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/IDataServiceQueryProvider/">IDataServiceQueryProvider</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/IDataServiceUpdateProvider/">IDataServiceUpdateProvider</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Relationships/">Relationships</category></item><item><title>Is hiding lower level APIs bad?</title><link>http://blogs.msdn.com/b/alexj/archive/2010/02/22/is-hiding-lower-level-apis-bad.aspx</link><pubDate>Mon, 22 Feb 2010 22:28:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9967667</guid><dc:creator>Alex D James</dc:creator><slash:comments>6</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/alexj/rsscomments.aspx?WeblogPostID=9967667</wfw:commentRss><comments>http://blogs.msdn.com/b/alexj/archive/2010/02/22/is-hiding-lower-level-apis-bad.aspx#comments</comments><description>&lt;P&gt;There are many good arguments for hiding away the lower layers in your stack – essentially the building blocks upon which your public API is built - however the ‘&lt;STRONG&gt;we don’t have the time and resources to test that layer completely&lt;/STRONG&gt;’ argument seems a little flawed to me.&lt;/P&gt;
&lt;P&gt;Surely if you are sitting above a layer you have to test it thoroughly anyway?&lt;/P&gt;
&lt;P&gt;And if the lower layer is all locked away, private or internal, that is going to be a LOT harder.&lt;/P&gt;
&lt;P&gt;Imagine somebody trying to paint the bottom of a &lt;A href="http://en.wikipedia.org/wiki/Tab_(beverage_can)" mce_href="http://en.wikipedia.org/wiki/Tab_(beverage_can)"&gt;can through an open stay tab&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/WhydowehavetohideawaylowerlevelAPIs_BE6D/photo_2.jpg" mce_href="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/WhydowehavetohideawaylowerlevelAPIs_BE6D/photo_2.jpg"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title=photo border=0 alt=photo src="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/WhydowehavetohideawaylowerlevelAPIs_BE6D/photo_thumb.jpg" width=504 height=379 mce_src="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/WhydowehavetohideawaylowerlevelAPIs_BE6D/photo_thumb.jpg"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;Not exactly the easiest thing in the world. But that is exactly what testing a private lower level API is like.&lt;/P&gt;
&lt;P&gt;It would be much easier if you had complete and unfettered access to the inside of the can / lower level.&lt;/P&gt;
&lt;P&gt;So if you have to test that surface anyway why not just make it public?&lt;/P&gt;
&lt;H3&gt;Counter Arguments?&lt;/H3&gt;
&lt;P&gt;Well, like all programming decisions, it’s not quite that simple. There are many nuances.&lt;/P&gt;
&lt;P&gt;What for example if exposing your lower level API…&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Just isn’t that useful to your target audience?&lt;/LI&gt;
&lt;LI&gt;Requires too much orchestration and non-obvious call orders?&lt;/LI&gt;
&lt;LI&gt;Exposes you to more legal obligations?&lt;/LI&gt;
&lt;LI&gt;Would require a lot of supporting work like documentation etc?&lt;/LI&gt;
&lt;LI&gt;Might be wrong, and you don’t want to be locked into the current design forever?&lt;/LI&gt;
&lt;LI&gt;Means your software is no longer opinionated?&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;I’m sure you can think of many similar pivots.&lt;/P&gt;
&lt;P&gt;That there are good reasons to keep things internal is beyond debate, what I hope everyone realizes though is that test cost alone probably&amp;nbsp;isn’t reason enough.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9967667" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Philosophical/">Philosophical</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Ramblings/">Ramblings</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Musings/">Musings</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Testing/">Testing</category></item><item><title>Tip 54 – How to improve performance using Statement Expressions</title><link>http://blogs.msdn.com/b/alexj/archive/2010/02/13/tip-54-how-to-improve-performance-using-statement-expressions.aspx</link><pubDate>Sat, 13 Feb 2010 17:27:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9963110</guid><dc:creator>Alex D James</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/alexj/rsscomments.aspx?WeblogPostID=9963110</wfw:commentRss><comments>http://blogs.msdn.com/b/alexj/archive/2010/02/13/tip-54-how-to-improve-performance-using-statement-expressions.aspx#comments</comments><description>&lt;h3&gt;Background:&lt;/h3&gt;  &lt;p&gt;While writing the &lt;a href="http://blogs.msdn.com/alexj/archive/2010/02/11/creating-a-data-service-provider-part-7-update.aspx" mce_href="http://blogs.msdn.com/alexj/archive/2010/02/11/creating-a-data-service-provider-part-7-update.aspx"&gt;update post&lt;/a&gt; in my Data Service Provider series I ended up writing this block of reflection code to copy properties values from one object to another:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;foreach (var prop in resourceType&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Properties&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Where(p =&amp;gt; (p.Kind &amp;amp; ResourcePropertyKind.Key)&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; != ResourcePropertyKind.Key))       &lt;br&gt;{&amp;nbsp;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var clrProp = clrType       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .GetProperties()       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Single(p =&amp;gt; p.Name == prop.Name);&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var defaultPropValue = clrProp       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .GetGetMethod()       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Invoke(resetTemplate, new object[] { });&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; clrProp&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .GetSetMethod()       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Invoke(resource, new object[] { defaultPropValue });&amp;nbsp; &lt;br&gt;} &lt;/font&gt;&lt;/p&gt;  &lt;h3&gt;Problem:&lt;/h3&gt;  &lt;p&gt;This code has at least two major problems. &lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;It is finding properties and methods via reflection in a loop &lt;/li&gt;    &lt;li&gt;It is invoking those methods using reflection in a loop. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;We could address (1) by storing all the property get / set methods in some cacheable data-structure.&lt;/p&gt;  &lt;p&gt;But fixing (2) is a little more tricky, to make this code truly generic you need to use something like lightweight code-gen, or worse.&lt;/p&gt;  &lt;h3&gt;Solution:&lt;/h3&gt;  &lt;p&gt;Thankfully .NET 4.0 adds statement expressions. Which means you can create expressions that describe multi-line statements now, and yes those statements can do things like assignments.    &lt;br&gt;    &lt;br&gt;Picture Borat saying ‘Nice…’&lt;/p&gt;  &lt;p&gt;A quick search of the interweb revealed this &lt;a href="http://community.bartdesmet.net/blogs/bart/archive/2009/08/10/expression-trees-take-two-introducing-system-linq-expressions-v4-0.aspx" mce_href="http://community.bartdesmet.net/blogs/bart/archive/2009/08/10/expression-trees-take-two-introducing-system-linq-expressions-v4-0.aspx"&gt;excellent post on statement expressions by Bart&lt;/a&gt;, and that was enough to get me – and I hope you – to get excited.&lt;/p&gt;  &lt;h4&gt;Step 1 – Getting familiar with the API&lt;/h4&gt;  &lt;p&gt;Armed with my new found enthusiasm I decided to dip my toes in the water with something simple, namely trying to convert this into an expression:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;Func&amp;lt;int&amp;gt; func = () =&amp;gt; {      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int n;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; n=2;       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return n;       &lt;br&gt;};&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;It would be awesome if you could just do this:&lt;/p&gt;  &lt;p&gt;&lt;font color="#ff0000" face="Courier New"&gt;Expression&amp;lt;Func&amp;lt;int&amp;gt;&amp;gt; expr = () =&amp;gt; {      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int n;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; n = 2;       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return n;       &lt;br&gt;};&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;But unfortunately C# doesn’t support this today, instead you have to manually construct the expression, like this:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;var n = Expression.Variable(typeof(int));      &lt;br&gt;var expr = Expression.Lambda&amp;lt;Func&amp;lt;int&amp;gt;&amp;gt;       &lt;br&gt;(       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Expression.Block(       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // int n;       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new[] { n },       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // n = 2;       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Expression.Assign(       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; n,       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Expression.Constant(2)       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ),       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // return n;&lt;/font&gt;&lt;font face="Courier New"&gt;      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; n       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; )       &lt;br&gt;);&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Pretty easy huh. &lt;/p&gt;  &lt;h4&gt;Step 2 – Proving we can assign to a property&lt;/h4&gt;  &lt;p&gt;Now we’ve got a feel for the API, it’s time to start applying it to our problem.&lt;/p&gt;  &lt;p&gt;What we need is a function that will modify an Object (in this case a product) by resetting one or more of its properties, like this:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;Action&amp;lt;Product&amp;gt; baseReset = (Product p) =&amp;gt; { p.Name = null; };&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;This code creates an equivalent action using the new expression APIs:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;var parameter = Expression.Parameter(typeof(Product));&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;var resetExpr = Expression.Lambda&amp;lt;Action&amp;lt;Product&amp;gt;&amp;gt;(       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Expression.Block(       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Expression.Assign(       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Expression.Property(parameter,"Name"),       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Expression.Constant(null, typeof(string))       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; )       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ),       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; parameter       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; );       &lt;br&gt;var reset = resetExpr.Compile();       &lt;br&gt;var product = new Product { ID = 1, Name = "Foo" };       &lt;br&gt;reset(product);&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;And sure enough after reset(product) is called the product Name is null. &lt;/p&gt;  &lt;h4&gt;Step 3 – Assigning to all non key properties&lt;/h4&gt;  &lt;p&gt;Now all we need to do is create a function that when given a particular CLR type will create an expression to reset all the non-key properties. &lt;/p&gt;  &lt;p&gt;Actually collecting the list of properties and their intended values, isn’t interesting for this discussion, so lets imagine we’ve already got that information in a dictionary, like this:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;var properties = new Dictionary&amp;lt;PropertyInfo, object&amp;gt;();      &lt;br&gt;var productProperties = typeof(Product).GetProperties();&lt;/font&gt;&lt;font face="Courier New"&gt;      &lt;br&gt;var nameProp = productProperties.Single(p =&amp;gt; p.Name == "Name");       &lt;br&gt;var costProp = productProperties.Single(p =&amp;gt; p.Name == "Cost");       &lt;br&gt;properties.Add(nameProp, null);       &lt;br&gt;properties.Add(costProp, 0.0M);&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Given this data-structure our job is to create an expression that has the same affect as this action:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;Action&amp;lt;Product&amp;gt; baseReset = (Product p) =&amp;gt; {      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; p.Name = null;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; p.Cost = 0.0M;       &lt;br&gt;};&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;First we need to create all the assignment expressions:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;var parameter = Expression.Parameter(typeof(Product));      &lt;br&gt;List&amp;lt;Expression&amp;gt; assignments = new List&amp;lt;Expression&amp;gt;();       &lt;br&gt;foreach (var property in properties.Keys)       &lt;br&gt;{       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; assignments.Add(Expression.Assign(       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Expression.Property(parameter, property.Name),       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Expression.Convert(       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Expression.Constant(       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; properties[property],       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; property.PropertyType       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; )       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; )       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; );       &lt;br&gt;}&lt;/font&gt;&amp;nbsp;&amp;nbsp; &lt;/p&gt;  &lt;p&gt;Next we feed the assignment expressions into a block inside a lambda, compile the whole thing and test out our nifty new function:    &lt;br&gt;    &lt;br&gt;&lt;font face="Courier New"&gt;var resetExpr = Expression.Lambda&amp;lt;Action&amp;lt;Product&amp;gt;&amp;gt;(      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Expression.Block(       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; assignments.ToArray()       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ),       &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; parameter       &lt;br&gt;);       &lt;br&gt;var reset = resetExpr.Compile();       &lt;br&gt;var product = new Product { ID = 1, Name = "Foo", Cost = 34.5M };       &lt;br&gt;reset(product);       &lt;br&gt;Debug.Assert(product.Name == null);       &lt;br&gt;Debug.Assert(product.Cost == 0.0M);&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;As expected this works like a charm.&lt;/p&gt;  &lt;p&gt;To solve the problem I had in my Update Post, we’d need a dictionary keyed on type, that we can used to store the reset action for a particular type. Then if a type’s reset action it isn’t found we just create it…&lt;/p&gt;  &lt;p&gt;And our performance problem should be a thing of the past :)&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9963110" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/alexj/archive/tags/C_2300_/">C#</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Expressions/">Expressions</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Tips/">Tips</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Statement+Expression/">Statement Expression</category></item><item><title>Tip 53 – How to debug EF POCO mapping issues</title><link>http://blogs.msdn.com/b/alexj/archive/2010/02/12/tip-53-how-to-debug-ef-poco-mapping-issues.aspx</link><pubDate>Fri, 12 Feb 2010 00:50:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9962354</guid><dc:creator>Alex D James</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/alexj/rsscomments.aspx?WeblogPostID=9962354</wfw:commentRss><comments>http://blogs.msdn.com/b/alexj/archive/2010/02/12/tip-53-how-to-debug-ef-poco-mapping-issues.aspx#comments</comments><description>&lt;P&gt;If you are trying to use POCO classes in EF 4.0, it is relatively easy to run into problems with the mapping from your model to your CLR classes.&lt;/P&gt;
&lt;P&gt;If you get any nasty problems here, the best way to get to the bottom of things is to try to explicitly load the metadata for your POCO types.&lt;/P&gt;
&lt;P&gt;For example if Product is a POCO type and you are having problems getting it working, you can try this code to see what the problem is:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;using (MyContext ctx = new MyContext()) &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp; ctx.MetadataWorkspace.LoadFromAssembly( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; typeof(Product).Assembly, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MappingWarning &lt;BR&gt;&amp;nbsp;&amp;nbsp; ); &lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Where MappingWarning could be any action / method that takes a string and returns void, like for example:&lt;/P&gt;&lt;FONT face="Courier New"&gt;public void MappingWarning(string warning) &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(warning); &lt;BR&gt;}&lt;/FONT&gt; 
&lt;P&gt;Now when you do this, EF will loop over the types in your assembly trying to see if they map to types in the Conceptual Model, if some reason a CLR&amp;nbsp;type is identified and subsequently&amp;nbsp;disqualified – isn’t a valid match – your action with be called, and in our example the warning will be pumped out to the Console.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9962354" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/alexj/archive/tags/EF/">EF</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Tips/">Tips</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/POCO/">POCO</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/EF+4-0/">EF 4.0</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Debugging/">Debugging</category></item><item><title>Creating a Data Service Provider – Part 7 – Update</title><link>http://blogs.msdn.com/b/alexj/archive/2010/02/11/creating-a-data-service-provider-part-7-update.aspx</link><pubDate>Thu, 11 Feb 2010 23:06:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9962315</guid><dc:creator>Alex D James</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/alexj/rsscomments.aspx?WeblogPostID=9962315</wfw:commentRss><comments>http://blogs.msdn.com/b/alexj/archive/2010/02/11/creating-a-data-service-provider-part-7-update.aspx#comments</comments><description>&lt;p&gt;In &lt;a href="http://blogs.msdn.com/alexj/archive/2010/01/07/data-service-providers-getting-started.aspx" mce_href="http://blogs.msdn.com/alexj/archive/2010/01/07/data-service-providers-getting-started.aspx"&gt;Parts 1 thru 6&lt;/a&gt; we created a custom Read/Only provider over an in memory list of Products.&lt;/p&gt;
&lt;p&gt;Now it’s time to add update support.&lt;/p&gt;
&lt;p&gt;To do that we need to add an implementation of &lt;b&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataserviceupdateprovider%28VS.100%29.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataserviceupdateprovider(VS.100).aspx"&gt;IDataServiceUpdateProvider&lt;/a&gt;&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;But first lets talk about the…&lt;/p&gt;
&lt;h3&gt;Implications of Batching&lt;/h3&gt;
&lt;p&gt;The &lt;b&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataserviceupdateprovider%28VS.100%29.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataserviceupdateprovider(VS.100).aspx"&gt;IDataServiceUpdateProvider&lt;/a&gt;&amp;nbsp;&lt;/b&gt;interface is designed to support Batching, allowing customers to update many Resources in one transaction.&lt;/p&gt;
&lt;p&gt;Indeed because the interface itself is low level – there is a API call needed to update every individual property – even just updating a single resource can result in a batch of API calls that should happen atomically: if an API call fails we need to rollback / abort whatever happened earlier.&lt;/p&gt;
&lt;p&gt;All this means you can expect to see a number of calls to methods like IDataServiceUpdateProvider.SetValue(..), before each SaveChanges() call.&lt;/p&gt;
&lt;p&gt;This seems simple enough, but it has profound implications on how you implement the interface. &lt;/p&gt;
&lt;p&gt;You can’t just blindly apply the requested change as it is made. You need a way of recording and then committing or aborting all requested changes as a group.&lt;/p&gt;
&lt;p&gt;If your data is in a database this typically means recording a series of commands and issuing them in a single transaction. Which something like the Entity Framework does for you automatically.&lt;/p&gt;
&lt;p&gt;If however your data is memory, like the sample we’ve been building, you basically have to record intent, and apply that intent only when SaveChanges() is called.&lt;/p&gt;
&lt;p&gt;This is why our implementation creates and records Actions whenever one of these low level changes is made…&lt;/p&gt;
&lt;h3&gt;Making our DSPContext Updatable.&lt;/h3&gt;
&lt;p&gt;Another prerequisite to implementing &lt;b&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataserviceupdateprovider%28VS.100%29.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataserviceupdateprovider(VS.100).aspx"&gt;IDataServiceUpdateProvider&lt;/a&gt;&amp;nbsp;&lt;/b&gt;is having a data source that is updatable.&lt;/p&gt;
&lt;p&gt;You can do this in a million different ways, but for the purpose of illustration I’ve decided to add some new abstract methods, to our DSPContent class, for Creating Resources, Adding Resources, Deleting Resources and Saving Changes, like this:&amp;nbsp; &lt;br&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;public abstract object CreateResource(ResourceType resourceType);&amp;nbsp; &lt;br&gt;&lt;br&gt;public abstract void AddResource(ResourceType resourceType, &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; object resource);&amp;nbsp; &lt;br&gt;&lt;br&gt;public abstract void DeleteResource(object resource); &lt;br&gt;&lt;br&gt;public abstract void SaveChanges(); &lt;/font&gt;&lt;/p&gt;
&lt;p&gt;Then in our derived ProductsContext we implement these new methods like this:&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;public override object CreateResource(ResourceType resourceType) &lt;br&gt;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (resourceType.InstanceType == typeof(Product)) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return new Product(); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new NotSupportedException( &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string.Format("{0} not found", resourceType.FullName) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ); &lt;br&gt;} &lt;br&gt;&lt;/font&gt;&lt;br&gt;&lt;font face="Courier New"&gt;public override void AddResource( &lt;br&gt;&amp;nbsp;&amp;nbsp; ResourceType resourceType, &lt;br&gt;&amp;nbsp;&amp;nbsp; object resource) &lt;br&gt;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (resourceType.InstanceType == typeof(Product)) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Product p = resource as Product;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (p != null){ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font face="Courier New"&gt;Products.Add(p);&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new NotSupportedException("Type not found"); &lt;br&gt;}&lt;/font&gt; &lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;public override void DeleteResource( &lt;br&gt;&amp;nbsp;&amp;nbsp; object resource) &lt;br&gt;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (resource.GetType() == typeof(Product)) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Products.Remove(resource as Product); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new NotSupportedException("Type not found"); &lt;br&gt;} &lt;br&gt;&lt;br&gt;public override void SaveChanges() &lt;br&gt;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var prodKey = Products.Max(p =&amp;gt; p.ProdKey); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach (var prod in Products.Where(p =&amp;gt; p.ProdKey == 0)) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; prod.ProdKey = ++prodKey; &lt;br&gt;}&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;As you can see each of these methods are pretty simple, except for SaveChanges which mimics a database Identity column by assigning every new Product (ProdKey == 0) a Unique sequential ID.&lt;/p&gt;
&lt;p&gt;Which means we are finally ready to… &lt;/p&gt;
&lt;h3&gt;Implement IDataServiceUpdateProvider&lt;/h3&gt;
&lt;p&gt;Our implementation is called DSPUpdateProvider and looks like this:&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;public class DSPUpdateProvider&amp;lt;T&amp;gt;: IDataServiceUpdateProvider&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; where T: DSPContext&lt;/font&gt; &lt;br&gt;&lt;br&gt;As you can see it is a generic class where T is the type of our DataSource. &lt;br&gt;&lt;br&gt;The IDataServiceUpdateProvider interface doesn’t have any methods to give us the DSPContext - so we’ll need to get it via the constructor somehow – remember we are in charge of constructing the provider through our implementation of IServiceProvider. :)&lt;/p&gt;
&lt;p&gt;Metadata would be handy too, so the DSPUpdateProvider constructor takes both metadata and query providers as arguments:&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;public DSPUpdateProvider( &lt;br&gt;&amp;nbsp;&amp;nbsp; IDataServiceMetadataProvider metadata, &lt;br&gt;&amp;nbsp;&amp;nbsp; DSPQueryProvider&amp;lt;T&amp;gt; query) &lt;br&gt;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _metadata = metadata; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _query = query; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _actions = new List&amp;lt;Action&amp;gt;(); &lt;br&gt;}&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;The _actions list is there to batch a list of actions to invoke when IDataServiceUpdateProvider.SaveChanges() is called.&amp;nbsp; &lt;br&gt;&lt;br&gt;As you remember we can’t ‘really’ update our Data Source until Data Services tells us to.&lt;/p&gt;
&lt;h4&gt;Getting the DataSource&lt;/h4&gt;
&lt;p&gt;Next we are going to need a way to get to the DataSource i.e. the class that derives from DSPContext. So we need something like this:&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;public T GetContext() &lt;br&gt;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return (_query.CurrentDataSource as T); &lt;br&gt;}&lt;/font&gt; &lt;/p&gt;
&lt;p&gt;Which simply gets the CurrentDataSource from the IDataServiceQueryProvider, and casts it to T which, if you remember, is a class derived from DSPContext. &lt;/p&gt;
&lt;h4&gt;Creating Resources&lt;/h4&gt;
&lt;p&gt;Next whenever someone does an insert (aka POST) Data Services needs a way of creating the object backing the Resource – CreateResource – our implementation looks like this:&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;public object CreateResource( &lt;br&gt;&amp;nbsp;&amp;nbsp; string containerName, &lt;br&gt;&amp;nbsp;&amp;nbsp; string fullTypeName) &lt;br&gt;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ResourceType type = null; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (_metadata.TryResolveResourceType(fullTypeName, out type)) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var context = GetContext(); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var resource = context.CreateResource(type); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _actions.Add( &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; () =&amp;gt; context.AddResource(type, resource) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return resource; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new Exception( &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string.Format("Type {0} not found", fullTypeName) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ); &lt;br&gt;}&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;Here we try to create an instance of the CLR type used for a particular ResourceType.&lt;/p&gt;
&lt;p&gt;Notice that we create a Resource, but we don’t Add it immediately to our Data Source, instead we create and queue an action that will add the resource to the Data Source when invoked.&lt;/p&gt;
&lt;h4&gt;Getting a Resource&lt;/h4&gt;
&lt;p&gt;When Data Services tries to Update or Delete a Resource, it first needs to retrieve it (or a representation of it). Which is where IDataServiceUpdateProvider.GetResource(..) comes in.&lt;/p&gt;
&lt;p&gt;Data Services passes an IQueryable that when invoked should return exactly one resource.&lt;/p&gt;
&lt;p&gt;You might ask why Data Services doesn’t just get the resource itself?&lt;/p&gt;
&lt;p&gt;Well the reason is that this method provides and extra layer of indirection which allows you to return something that ‘represents’ the resource, aka a proxy.&amp;nbsp; &lt;br&gt;&lt;br&gt;You could for example use this ‘proxy’ to record changes and then committing them in batch when SaveChanges() is called, thereby avoid Actions altogether.&lt;/p&gt;
&lt;p&gt;But in our implementation we’ve chosen the Action approach, so we can simply return the resource directly.&amp;nbsp; &lt;br&gt;&lt;br&gt;So we get the resource, check that there is only one matching resource and if the ResourceType is known – which it isn’t for deletes –&amp;nbsp;we also check&amp;nbsp;that the resource has the expected CLR type. &lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;public object GetResource(IQueryable query, string fullTypeName) &lt;br&gt;{ &lt;br&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp; var enumerator = query.GetEnumerator(); &lt;br&gt;&amp;nbsp;&amp;nbsp; if (!enumerator.MoveNext())&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new Exception("Resource not found"); &lt;br&gt;&amp;nbsp;&amp;nbsp; var resource = enumerator.Current; &lt;br&gt;&amp;nbsp;&amp;nbsp; if (enumerator.MoveNext()) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new Exception("Resource not uniquely identified"); &lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp; if (fullTypeName != null) &lt;br&gt;&amp;nbsp;&amp;nbsp; { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ResourceType type = null; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (!_metadata.TryResolveResourceType( &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; fullTypeName, out type)) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new Exception("ResourceType not found"); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (!type.InstanceType.IsAssignableFrom(resource.GetType())) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new Exception("Unexpected resource type"); &lt;br&gt;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&amp;nbsp;&amp;nbsp; return resource;&lt;/font&gt;&lt;font face="Courier New"&gt; &lt;br&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;}&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;Closely related is the IDataServiceUpdateProvider.ResolveResource(..) method. &lt;br&gt;&lt;br&gt;When you implement this method you are passed whatever your returned from GetResource(..) – which remember might have been a proxy – and are expected to return the real resource. &lt;/p&gt;
&lt;p&gt;Because we don’t use proxies, our implementation is essentially a no-op:&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;public object ResolveResource(object resource) &lt;br&gt;{ &lt;br&gt;&amp;nbsp;&amp;nbsp; return resource; &lt;br&gt;}&lt;/font&gt;&lt;/p&gt;
&lt;h4&gt;Updating Property Values&lt;/h4&gt;
&lt;p&gt;Once Data Services has the resource (or proxy for the resource), it will start updating it, by calling IDataServicesUpdateProvider.SetValue(..) to update each property in turn. &lt;/p&gt;
&lt;p&gt;By now you know the drill, we are going to record an action to set the property value rather than setting it immediately.&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;public void SetValue( &lt;br&gt;&amp;nbsp;&amp;nbsp; object targetResource, &lt;br&gt;&amp;nbsp;&amp;nbsp; string propertyName, &lt;br&gt;&amp;nbsp;&amp;nbsp; object propertyValue) &lt;br&gt;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // TODO: add some asserts!!! &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _actions.Add( &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; () =&amp;gt; ReallySetValue( &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; targetResource, &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; propertyName,&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; propertyValue) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ); &lt;br&gt;} &lt;br&gt;public void ReallySetValue( &lt;br&gt;&amp;nbsp;&amp;nbsp; object targetResource, &lt;br&gt;&amp;nbsp;&amp;nbsp; string propertyName, &lt;br&gt;&amp;nbsp;&amp;nbsp; object propertyValue) &lt;br&gt;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; targetResource &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .GetType() &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .GetProperties() &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Single(p =&amp;gt; p.Name == propertyName) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .GetSetMethod() &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Invoke(targetResource, new[] { propertyValue }); &lt;br&gt;}&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;As you can see the ReallySetValue (sorry for the unimaginative name) uses reflection to set the property. &lt;/p&gt;
&lt;p&gt;You might be tempted to remove this Reflection code to can speed this code up, but before you do all that work remember the real latency is related to OData / Atom serialization and deserialization and network latency, so it might not actually be worth the effort.&lt;/p&gt;
&lt;h4&gt;Getting Property Values&lt;/h4&gt;
&lt;p&gt;Occasionally during updates Data Services needs to Get the value of a property, if so it will use the IDataServiceUpdateProvider.GetValue(..) method. Because this GetValue is non-mutating we don’t can just go and get the value directly using a little reflection code:&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;public object GetValue(object targetResource, string propertyName) &lt;br&gt;{ &lt;br&gt;&amp;nbsp;&amp;nbsp; var value = targetResource &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .GetType() &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .GetProperties() &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Single(p =&amp;gt; p.Name == propertyName) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .GetGetMethod() &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Invoke(targetResource, new object[] { }); &lt;br&gt;&amp;nbsp;&amp;nbsp; return value; &lt;br&gt;}&lt;/font&gt;&lt;/p&gt;
&lt;h4&gt;Deleting Resources&lt;/h4&gt;
&lt;p&gt;Next we need to handle Deletes. This code is pretty self explanatory, we record an action to delete the resource later.&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;public void DeleteResource(object targetResource) &lt;br&gt;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _actions.Add(() =&amp;gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GetContext().DeleteResource(targetResource) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ); &lt;br&gt;}&lt;/font&gt;&lt;/p&gt;
&lt;h4&gt;Resetting Resources&lt;/h4&gt;
&lt;p&gt;By default there is no need to reset a resource, but a client can request this, for example by using: &lt;br&gt;&lt;br&gt;&lt;font face="Courier New"&gt;SaveChanges(SaveChangesOptions.ReplaceOnUpdate); &lt;br&gt;&lt;/font&gt;&lt;br&gt;If this happens Data Services will ask your IDataServiceUpdateProvider implementation to&amp;nbsp;reset all the&amp;nbsp;non-key properties of the Resource by calling ResetResource(..). &lt;/p&gt;
&lt;p&gt;Here's our implementation:&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;public object ResetResource(object resource) &lt;br&gt;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _actions.Add(() =&amp;gt; ReallyResetResource(resource)); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return resource; &lt;br&gt;}&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;Which uses this to do the actual work:&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;public void ReallyResetResource(object resource) &lt;br&gt;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Create an new 'blank' instance of the resource &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var clrType = resource.GetType(); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ResourceType resourceType = &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _metadata.Types.Single(t =&amp;gt; t.InstanceType == clrType); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var resetTemplate = GetContext().CreateResource(resourceType); &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Copy non-key property values from the 'blank' resource &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach (var prop in resourceType &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Properties &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Where(p =&amp;gt; (p.Kind &amp;amp; ResourcePropertyKind.Key)&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; != ResourcePropertyKind.Key)) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Obviously for perf reasons you could might want to &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // cache the result of these reflection calls. &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var clrProp = clrType &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .GetProperties() &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Single(p =&amp;gt; p.Name == prop.Name); &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var defaultPropValue = clrProp &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .GetGetMethod() &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Invoke(resetTemplate, new object[] { }); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; clrProp &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .GetSetMethod() &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Invoke(resource, new object[] { defaultPropValue }); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;}&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;As you can see the approach used to reset non-key properties, is to create an new ‘blank’ resource, and copy property values across.&lt;/p&gt;
&lt;h4&gt;Saving Changes&lt;/h4&gt;
&lt;p&gt;Finally if everything goes according to plan, once all the property updates etc have been queued up you will see a request to IDataServiceUpdateProvider.SaveChanges().&lt;/p&gt;
&lt;p&gt;Because of how we’ve implemented things, this one is trivial for us:&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;public void SaveChanges() &lt;br&gt;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach (var a in _actions) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; a(); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; GetContext().SaveChanges(); &lt;br&gt;}&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;We simply invoke all the queued actions, and then ask the DSPContext to Save its changes, which if you remember, simply ensures that each new Product has a new ProdKey.&lt;/p&gt;
&lt;p&gt;If anything goes wrong you’ll get a ClearChanges() call, which is even simplier:&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;public void ClearChanges() &lt;br&gt;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _actions.Clear(); &lt;br&gt;}&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;And now we are done implementing &lt;b&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataserviceupdateprovider%28VS.100%29.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataserviceupdateprovider(VS.100).aspx"&gt;IDataServiceUpdateProvider&lt;/a&gt;&lt;/b&gt;. &lt;/p&gt;
&lt;p&gt;Yippee!&lt;/p&gt;
&lt;h4&gt;Missing methods&lt;/h4&gt;
&lt;p&gt;But wait a second … you might have noticed that we haven’t implemented a number of the methods on the interface:&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;SetReference(..) &lt;br&gt;AddReferenceToCollection(..) &lt;br&gt;RemoveReferenceToCollection(..) &lt;br&gt;SetConcurrencyValues(..)&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;That’s because we don’t have any Relationships or ETags, so these methods will never be called, meaning we can safely ignore them for now. &lt;/p&gt;
&lt;p&gt;Don’t worry though I’ll cover them in a future post.&lt;/p&gt;
&lt;h3&gt;Hooking it all together&lt;/h3&gt;
&lt;p&gt;The last step is to modify our IServiceProvider implementation to construct our DSPUpdateProvider and returned it whenever Data Services asked for the IDataServiceUpdateProvider interface.&lt;/p&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;The key to implementing &lt;b&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataserviceupdateprovider%28VS.100%29.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataserviceupdateprovider(VS.100).aspx"&gt;IDataServiceUpdateProvider&lt;/a&gt;&amp;nbsp;&lt;/b&gt;is realizing that you need to be able to delay execution. You can do that using either Proxy objects or Actions, like the above implementation. &lt;/p&gt;
&lt;p&gt;Once you know how you are going to handle the atomicity requirements, and you understand what each method is supposed to do, it is actually a pretty mechanical exercise of going through an implementing each method in turn.&lt;/p&gt;
&lt;p&gt;Next up we’ll look at &lt;a href="http://blogs.msdn.com/alexj/archive/2010/02/24/creating-a-data-service-provider-part-8-relationships.aspx" mce_href="http://blogs.msdn.com/alexj/archive/2010/02/24/creating-a-data-service-provider-part-8-relationships.aspx"&gt;adding relationships&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9962315" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Astoria/">Astoria</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Data+Services/">Data Services</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/DSP/">DSP</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/IDataServiceUpdateProvider/">IDataServiceUpdateProvider</category></item><item><title>Tip 52 – How to re-use Types with the Data Services client</title><link>http://blogs.msdn.com/b/alexj/archive/2010/01/27/tip-52-how-to-re-use-types-with-the-data-services-client.aspx</link><pubDate>Wed, 27 Jan 2010 22:52:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9954382</guid><dc:creator>Alex D James</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/alexj/rsscomments.aspx?WeblogPostID=9954382</wfw:commentRss><comments>http://blogs.msdn.com/b/alexj/archive/2010/01/27/tip-52-how-to-re-use-types-with-the-data-services-client.aspx#comments</comments><description>&lt;p&gt;By default when you add a Data Service Service Reference you get automatic code-generation, which produces a strongly typed DataServiceContext and classes for all your ResourceTypes.&lt;/p&gt;
&lt;p&gt;You can have a look at this generated code if you ‘show all files’ in your project:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/Tip52HowtoreuseTypeswiththeDataServicesc_CE5E/ShowAllFiles.png" mce_href="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/Tip52HowtoreuseTypeswiththeDataServicesc_CE5E/ShowAllFiles.png"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/Tip52HowtoreuseTypeswiththeDataServicesc_CE5E/ShowAllFiles_thumb.png" style="border: 0px none ; display: inline;" title="ShowAllFiles" alt="ShowAllFiles" mce_src="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/Tip52HowtoreuseTypeswiththeDataServicesc_CE5E/ShowAllFiles_thumb.png" width="138" border="0" height="51"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;And then expand your &lt;b&gt;Data Service Reference, &lt;/b&gt;it’s dependant &lt;b&gt;Reference.datasvcma&lt;/b&gt;p and open up the &lt;b&gt;Reference.cs&lt;/b&gt; file: &lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/Tip52HowtoreuseTypeswiththeDataServicesc_CE5E/SampleServiceReference.png" mce_href="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/Tip52HowtoreuseTypeswiththeDataServicesc_CE5E/SampleServiceReference.png"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/Tip52HowtoreuseTypeswiththeDataServicesc_CE5E/SampleServiceReference_thumb.png" style="border: 0px none ; display: inline;" title="SampleServiceReference" alt="SampleServiceReference" mce_src="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/Tip52HowtoreuseTypeswiththeDataServicesc_CE5E/SampleServiceReference_thumb.png" width="217" border="0" height="95"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Step 1 – Turn off Code-Gen&lt;/h3&gt;
&lt;p&gt;If however you want to re-use some existing classes you’ll have to turn this off Code Gen.&lt;/p&gt;
&lt;p&gt;Which is pretty easy – select the &lt;b&gt;Reference.datasvcmap&lt;/b&gt; file and go to its &lt;b&gt;Properties&lt;/b&gt;, and then clear the &lt;b&gt;Custom Tool&lt;/b&gt;, which by default says ‘DataServiceClientGenerator’.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;a href="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/Tip52HowtoreuseTypeswiththeDataServicesc_CE5E/SampleServiceReferenceNoCodeGen.png" mce_href="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/Tip52HowtoreuseTypeswiththeDataServicesc_CE5E/SampleServiceReferenceNoCodeGen.png"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/Tip52HowtoreuseTypeswiththeDataServicesc_CE5E/SampleServiceReferenceNoCodeGen_thumb.png" style="border: 0px none ; display: inline;" title="SampleServiceReferenceNoCodeGen" alt="SampleServiceReferenceNoCodeGen" mce_src="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/Tip52HowtoreuseTypeswiththeDataServicesc_CE5E/SampleServiceReferenceNoCodeGen_thumb.png" width="475" border="0" height="485"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;h3&gt;Step 2 – Create a strongly typed DataServiceContext:&lt;/h3&gt;
&lt;p&gt;When we’ve turned off code-gen we also lost the strongly typed DataServiceContext which just makes programming a little more convenient. &lt;/p&gt;
&lt;p&gt;Well it’s pretty simple code that you can easily write yourself like this:&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;public class SampleServiceCtx: DataServiceContext &lt;br&gt;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public SampleServiceCtx(Uri serviceRoot) : base(serviceRoot) { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; base.ResolveName = ResolveNameFromType; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; base.ResolveType = ResolveTypeFromName; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; protected Type ResolveTypeFromName(string typeName) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (typeName.StartsWith("Sample.")) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return this.GetType().Assembly.GetType( &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; typeName.Replace("Sample.", "Tip52.") &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; false); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return null; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; protected string ResolveNameFromType(Type clientType) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (clientType.Namespace.Equals("Tip52")) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return "Sample." + clientType.Name; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return null; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public DataServiceQuery&amp;lt;Product&amp;gt; Products { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return base.CreateQuery&amp;lt;Product&amp;gt;("Products"); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;}&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;Notice that the Products property simple returns DataServiceQuery&amp;lt;&lt;b&gt;Product&lt;/b&gt;&amp;gt; where &lt;b&gt;Product&lt;/b&gt; is the type we are trying to re-use.&lt;/p&gt;
&lt;p&gt;The key to making all this work is the code that maps from a Data Service Resource typeName to a client-side Type and visa versa. &lt;br&gt;&lt;br&gt;This mapping is handled by two Functions, which we tell the DataServiceContext about in our constructor. In this example you can see we are simply going from the ‘Tip52’ namespace on the client to the ‘Sample’ namespace on the server.&lt;/p&gt;
&lt;h3&gt;Step 3 – Try it out:&lt;/h3&gt;
&lt;p&gt;Once you’ve set up the resolvers you should be able to re-use your existing types with quite easily:&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;var root = new Uri("http://localhost/Tip52/sample.svc"); &lt;br&gt;var ctx = new SampleServiceCtx(root); &lt;br&gt;foreach (Product p in ctx.Products) &lt;br&gt;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("{0} costs {1}", p.Name, p.Price); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; p.Price += 0.30M; &lt;font color="#008000"&gt;// Cross the board price increases! &lt;br&gt;&lt;/font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ctx.UpdateObject(p); &lt;br&gt;} &lt;br&gt;ctx.SaveChanges();&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;That’s it. Nifty huh.&lt;/p&gt;
&lt;h3&gt;Caveats:&lt;/h3&gt;
&lt;p&gt;This only works if the property names&amp;nbsp;are the same on the client and server, because there is no way to rename properties.&lt;br&gt;&lt;br&gt;Also because of the way object materialization works in the Astoria client this won't work well if your class has a Reference property with a backing FK property AND the class does automatic fix-up to keep both values consistent.&lt;br&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9954382" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Tips/">Tips</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Data+Services/">Data Services</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/WCF/">WCF</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Data+Services+Client/">Data Services Client</category></item><item><title>Tip 51 – How to load EF metadata from arbitrary streams</title><link>http://blogs.msdn.com/b/alexj/archive/2010/01/27/tip-51-how-to-load-ef-metadata-from-an-arbitrary-stream.aspx</link><pubDate>Wed, 27 Jan 2010 00:18:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9953788</guid><dc:creator>Alex D James</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/alexj/rsscomments.aspx?WeblogPostID=9953788</wfw:commentRss><comments>http://blogs.msdn.com/b/alexj/archive/2010/01/27/tip-51-how-to-load-ef-metadata-from-an-arbitrary-stream.aspx#comments</comments><description>&lt;P&gt;In&amp;nbsp;&lt;A href="http://blogs.msdn.com/alexj/archive/2009/11/29/tip-45-how-to-swap-ef-metadata-at-runtime.aspx" mce_href="http://blogs.msdn.com/alexj/archive/2009/11/29/tip-45-how-to-swap-ef-metadata-at-runtime.aspx"&gt;Tip 45&lt;/A&gt; I showed you how to build a connection string at runtime, which is pretty nifty. &lt;/P&gt;
&lt;P&gt;The problem with that was that it relies on having metadata files (.csdl .ssdl and .msl)&amp;nbsp;on local disk.&lt;/P&gt;
&lt;P&gt;But what if they live on a web-server or something and you don’t even have access to the local file system to copy them locally? &lt;/P&gt;
&lt;P&gt;Well it turns out you can load the metadata from streams too, and this Tip shows you how.&lt;/P&gt;
&lt;H3&gt;Step 1: Get XmlTextReaders for the CSDL, MSL and SSDL:&lt;/H3&gt;
&lt;P&gt;This can be as simple as ‘new XmlTextReader(url)’. &lt;/P&gt;
&lt;P&gt;But in this example I’m going to show you how to do it from string variables, which of course you could have got from anywhere:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;string csdl = "…"; &lt;BR&gt;string ssdl = "…"; &lt;BR&gt;string msl = "…";&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;var csdlReader = new StringReader(csdl); &lt;BR&gt;var ssdlReader = new StringReader(ssdl); &lt;BR&gt;var mslReader = new StringReader(msl); &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;var csdlXmlReader = new XmlTextReader(csdlReader); &lt;BR&gt;var ssdlXmlReader = new XmlTextReader(ssdlReader); &lt;BR&gt;var mslXmlReader = new XmlTextReader(mslReader);&lt;/FONT&gt;&lt;/P&gt;
&lt;H3&gt;Step 2: Create metadata ItemCollections:&lt;/H3&gt;
&lt;P&gt;Next you need an EdmItemCollection for the CSDL, a StoreItemCollection for the SSDL and a StorageMappingItemCollection for the MSL:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;var edmItemCollection = new EdmItemCollection( &lt;BR&gt;&amp;nbsp;&amp;nbsp; new[] { csdlXmlReader } &lt;BR&gt;); &lt;BR&gt;var storeItemCollection = new StoreItemCollection( &lt;BR&gt;&amp;nbsp;&amp;nbsp; new[] { ssdlXmlReader } &lt;BR&gt;); &lt;BR&gt;var storeMappingItemCollection =&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp; new StorageMappingItemCollection( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; edmItemCollection,&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; storeItemCollection,&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new [] { mslXmlReader } &lt;BR&gt;&amp;nbsp;&amp;nbsp; );&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;The only one that is even remotely interesting is the StorageMappingItemCollection, which along with MSL needs the other ItemCollections to validate the mapping.&lt;/P&gt;
&lt;H3&gt;Step 3: Create a MetadataWorkspace:&lt;/H3&gt;
&lt;P&gt;Next you need to group the ItemCollections together in a MetadataWorkspace:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;var mdw = new MetadataWorkspace(); &lt;BR&gt;mdw.RegisterItemCollection(edmItemCollection); &lt;BR&gt;mdw.RegisterItemCollection(storeItemCollection); &lt;BR&gt;mdw.RegisterItemCollection(storeMappingItemCollection);&lt;/FONT&gt;&lt;/P&gt;
&lt;H3&gt;Step 4: Create an EntityConnection:&lt;/H3&gt;
&lt;P&gt;Finally we need an EntityConnection. To create an EntityConnection we need a native database connection - generally this is a SqlConnection, but of course because EF has a provider model it could be something else like Oracle:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;var sqlConnectionString = @"Data Source=.\SQLEXPRESS;Ini…"; &lt;BR&gt;var sqlConnection = new SqlConnection(sqlConnectionString); &lt;BR&gt;var entityConnection = new EntityConnection( &lt;BR&gt;&amp;nbsp;&amp;nbsp; metadataWorkspace, &lt;BR&gt;&amp;nbsp;&amp;nbsp; sqlConnection &lt;BR&gt;);&lt;/FONT&gt;&lt;/P&gt;
&lt;H3&gt;Step 5: Create ObjectContext and use as Required&lt;/H3&gt;
&lt;P&gt;The last step is to use the EntityConnection you just created to construct your ObjectContext and begin using as just like normal:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;using (var ctx = new ProductCategoryEntities(entityConnection)) &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach (var product in ctx.Products) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(product.Name); &lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;That’s it… not necessarily simple but easy enough once you know how.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9953788" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Metadata/">Metadata</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Tips/">Tips</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Entity+Framework/">Entity Framework</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/EF+4-0/">EF 4.0</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/EF+3-5/">EF 3.5</category></item><item><title>Creating a Data Service Provider – Part 6 – Query Interactions</title><link>http://blogs.msdn.com/b/alexj/archive/2010/01/25/creating-a-data-service-provider-part-6-query-interactions.aspx</link><pubDate>Mon, 25 Jan 2010 21:39:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9953212</guid><dc:creator>Alex D James</dc:creator><slash:comments>11</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/alexj/rsscomments.aspx?WeblogPostID=9953212</wfw:commentRss><comments>http://blogs.msdn.com/b/alexj/archive/2010/01/25/creating-a-data-service-provider-part-6-query-interactions.aspx#comments</comments><description>&lt;P&gt;Whenever I find myself implementing a series of interfaces to plug into a framework or server, I always find myself wondering how the server will call my implementations. &lt;/P&gt;
&lt;P&gt;For me this is about forming a mental model to simplify how I think about what I’m doing.&lt;/P&gt;
&lt;P&gt;In fact as I’ve been doing this DSP series I’ve come up with a sort of mental model for how Queries are handled in a Data Service.&lt;/P&gt;
&lt;P&gt;Here is some &lt;STRONG&gt;PSEUDO CODE&lt;/STRONG&gt; that captures my mental model of how these interfaces interact.&lt;/P&gt;
&lt;H3&gt;Scenario – Basic Query&lt;/H3&gt;
&lt;P&gt;Imagine a client issues a &lt;STRONG&gt;GET&lt;/STRONG&gt; request for &lt;STRONG&gt;/Sample.svc/Products(1)&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;The first thing that happens (in my model) is that the data service is initialized.&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#008000&gt;// Locate the IDSP interfaces&lt;/FONT&gt; &lt;BR&gt;var dataservice = …; &lt;BR&gt;IServiceProvider sp = dataservice as IServiceProvider; &lt;BR&gt;if (sp == null) &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp; &lt;FONT color=#008000&gt;// some other code I’ll go into another day !!!&lt;/FONT&gt; &lt;BR&gt;} &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#008000&gt;// Get the various DSP interface implementations&lt;/FONT&gt; &lt;BR&gt;IDataServiceMetadataProvider mdp = &lt;BR&gt;&amp;nbsp;&amp;nbsp; sp.GetService(typeof(IDataServiceMetadataProvider)); &lt;BR&gt;IDataServiceQueryProvider qp = &lt;BR&gt;&amp;nbsp;&amp;nbsp; sp.GetService(typeof(IDataServiceQueryProvider)); &lt;BR&gt;&lt;BR&gt;&lt;FONT color=#008000&gt;// Set the CurrentDataSource (if necessary) &lt;/FONT&gt;&lt;BR&gt;if (qp.CurrentDataSource == null) &lt;BR&gt;&amp;nbsp;&amp;nbsp; qp.CurrentDataSource = dataservice.CreateDataService(); &lt;BR&gt;&lt;BR&gt;&lt;FONT color=#008000&gt;// Find the Products resourceSet &lt;BR&gt;// (note we actually try for ServiceOperations first &lt;BR&gt;// but lets keep this simple)&lt;/FONT&gt; &lt;BR&gt;var resourceSet = null; &lt;BR&gt;if (!mdp.TryResolveResourceSet(“Products”, out resourceSet)) &lt;BR&gt;&amp;nbsp;&amp;nbsp; throw new Exception(“404”);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#008000&gt;// Get the queryable for the Products resourceSet &lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;IQueryable queryRoot = qp.GetQueryRootForResourceSet(resourceSet);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#008000 face="Courier New"&gt;// Compose expressions onto the IQueryable to represent the &lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#008000&gt;// options ($filter/$select etc) specified in the URL&lt;/FONT&gt; &lt;BR&gt;queryRoot = Compose(options, queryRoot);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#008000&gt;// Start writing response&lt;/FONT&gt; &lt;BR&gt;WriteStartODataFeed(); &lt;BR&gt;&lt;BR&gt;&lt;FONT color=#008000&gt;// Enumerate results&lt;/FONT&gt; &lt;BR&gt;foreach (object resource in queryRoot) &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;FONT color=#008000&gt;// Get the ResourceType for resource&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // NOTE: because of inheritance it might be a resourceType &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // derived from resourceSet.ResourceType&lt;/FONT&gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ResourceType type = qp.GetResourceType(type); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WriteResource(resource,type);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;} &lt;BR&gt;WriteEndODataFeed();&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;That’s it take it or leave it. &lt;/P&gt;
&lt;P&gt;Hopefully you found this ‘completely made up’ code useful for forming your own mental model of how your DSP will fit into the Data Services framework.&lt;/P&gt;
&lt;H3&gt;Next time&lt;/H3&gt;
&lt;P&gt;There are some things I’ve left out of the above ‘mental model’ for now, like how ServiceOperations and QueryInterceptors complicate things.&lt;/P&gt;
&lt;P&gt;We’ll flesh more of those complications out in future posts.&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/alexj/archive/2010/02/11/creating-a-data-service-provider-part-7-update.aspx" mce_href="http://blogs.msdn.com/alexj/archive/2010/02/11/creating-a-data-service-provider-part-7-update.aspx"&gt;Next time&lt;/A&gt; though it’s time to take our Read/Only strongly typed ResourceSet and make it Read/Write.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9953212" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Astoria/">Astoria</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Data+Services/">Data Services</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/DSP/">DSP</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Mental+Model/">Mental Model</category></item><item><title>Creating a Data Service Provider – Part 5 - Query</title><link>http://blogs.msdn.com/b/alexj/archive/2010/01/19/creating-a-data-service-provider-part-5-query.aspx</link><pubDate>Tue, 19 Jan 2010 23:49:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9950612</guid><dc:creator>Alex D James</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/alexj/rsscomments.aspx?WeblogPostID=9950612</wfw:commentRss><comments>http://blogs.msdn.com/b/alexj/archive/2010/01/19/creating-a-data-service-provider-part-5-query.aspx#comments</comments><description>&lt;P&gt;In &lt;A href="http://blogs.msdn.com/alexj/archive/2010/01/15/creating-a-data-service-provider-part-4-minimal-running-service.aspx" mce_href="http://blogs.msdn.com/alexj/archive/2010/01/15/creating-a-data-service-provider-part-4-minimal-running-service.aspx"&gt;Part 4&lt;/A&gt; of our &lt;A href="http://blogs.msdn.com/alexj/archive/2010/01/07/data-service-providers-getting-started.aspx" mce_href="http://blogs.msdn.com/alexj/archive/2010/01/07/data-service-providers-getting-started.aspx"&gt;series showing how to implement a Custom Data Service Provider&lt;/A&gt; we hooked up an incomplete implementation of &lt;A href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataservicequeryprovider%28VS.100%29.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataservicequeryprovider(VS.100).aspx"&gt;IDataServiceQueryProvider&lt;/A&gt;, just enough to get the ServiceDocument and &lt;B&gt;$metadata&lt;/B&gt; working.&lt;/P&gt;
&lt;P&gt;In this part we’ll get query working too. &lt;/P&gt;
&lt;P&gt;To do that we need to know where the data is going to come from – the DataSource – and we need to really implement &lt;A href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataservicequeryprovider%28VS.100%29.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataservicequeryprovider(VS.100).aspx"&gt;IDataServiceQueryProvider&lt;/A&gt;.&lt;/P&gt;
&lt;H3&gt;Creating a DataSource:&lt;/H3&gt;
&lt;P&gt;So where is our Product data going to live? &lt;/P&gt;
&lt;P&gt;How about a Context, a little like EF or L2S but in memory. First we need a base class.&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;public abstract class DSPContext &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public abstract IQueryable GetQueryable(ResourceSet set); &lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Next we need a strongly typed context to expose a Products resourceSet:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;public class ProductsContext: DSPContext &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private List&amp;lt;Product&amp;gt; _products = new List&amp;lt;Product&amp;gt;(); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public override IQueryable GetQueryable(ResourceSet set) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (set.Name == "Products") return Products.AsQueryable(); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new NotSupportedException( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT face="Courier New"&gt;string.Format("{0} not found", set.Name) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public List&amp;lt;Product&amp;gt; Products &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return _products; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Nothing too tricky here at all. As you can see the &lt;FONT face="Courier New"&gt;&lt;B&gt;ResourceSet&lt;/B&gt;&lt;/FONT&gt; is backed by a simple List.&lt;/P&gt;
&lt;P&gt;The only thing worth noting is that, because our data is in memory, we use &lt;FONT face="Courier New"&gt;&lt;B&gt;.AsQueryable()&lt;/B&gt;&lt;/FONT&gt; to get the LINQ to Objects implementation of IQueryable.&lt;/P&gt;
&lt;P&gt;Next we need to change the Sample service to use the ProductsContext as its DataSource:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;public class Sample : DSPDataService&amp;lt;ProductsContext&amp;gt; &lt;BR&gt;{&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Then we override &lt;FONT face="Courier New"&gt;&lt;B&gt;CreateDataSource&lt;/B&gt;&lt;/FONT&gt; in our Sample service, so that we can pre-populate the Products list with some data:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;protected override ProductsContext CreateDataSource() &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ProductsContext context = new ProductsContext(); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; context.Products.Add( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new Product { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ProdKey = 1, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Name = "Bovril", &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Cost = 4.35M, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Price = 6.49M &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; context.Products.Add( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new Product { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ProdKey = 2, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Name = "Marmite", &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Cost = 4.97M, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Price = 7.21M &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return context; &lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Finally we override the &lt;FONT face="Courier New"&gt;&lt;B&gt;GetQueryProvider&lt;/B&gt;&lt;/FONT&gt; method &lt;A href="http://blogs.msdn.com/alexj/archive/2010/01/15/creating-a-data-service-provider-part-4-minimal-running-service.aspx" mce_href="http://blogs.msdn.com/alexj/archive/2010/01/15/creating-a-data-service-provider-part-4-minimal-running-service.aspx"&gt;we added last time&lt;/A&gt; to look like this:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;public override IDataServiceQueryProvider GetQueryProvider( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IDataServiceMetadataProvider metadata) &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return new DSPQueryProvider&amp;lt;ProductsContext&amp;gt;(metadata); &lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;H3&gt;IDataServiceQueryProvider for strongly typed data:&lt;/H3&gt;
&lt;P&gt;Lets throw away our ‘running service only’ implementation from &lt;A href="http://blogs.msdn.com/alexj/archive/2010/01/15/creating-a-data-service-provider-part-4-minimal-running-service.aspx" mce_href="http://blogs.msdn.com/alexj/archive/2010/01/15/creating-a-data-service-provider-part-4-minimal-running-service.aspx"&gt;Part 4&lt;/A&gt;. &lt;/P&gt;
&lt;P&gt;It didn’t do anything useful anyway. &lt;/P&gt;
&lt;P&gt;What we need is a strongly typed in memory Query Provider:&lt;/P&gt;
&lt;P&gt;By ‘strongly typed’ I mean for every ResourceType and its Properties there needs to be a matching CLR type with matching properties.&lt;/P&gt;
&lt;P&gt;There isn’t that much code, so here it is: &lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;public class DSPQueryProvider&amp;lt;T&amp;gt; : IDataServiceQueryProvider where T : DSPContext &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; T _currentDataSource; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IDataServiceMetadataProvider _metadata; &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public DSPQueryProvider(IDataServiceMetadataProvider metadata) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _metadata = metadata; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public object CurrentDataSource &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get { return _currentDataSource;} &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; set { _currentDataSource = value as T; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IQueryable GetQueryRootForResourceSet( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ResourceSet resourceSet) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return _currentDataSource.GetQueryable(resourceSet);&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public ResourceType GetResourceType(object target) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Type type = target.GetType(); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return _metadata.Types &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Single(t =&amp;gt; t.InstanceType == type); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public bool IsNullPropagationRequired &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get {return true; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public object GetOpenPropertyValue( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; object target, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string propertyName) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new NotImplementedException(); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IEnumerable&amp;lt;KeyValuePair&amp;lt;string, object&amp;gt;&amp;gt; GetOpenPropertyValues(object target) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new NotImplementedException(); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public object GetPropertyValue( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; object target, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ResourceProperty resourceProperty) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new NotImplementedException(); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public object InvokeServiceOperation( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ServiceOperation serviceOperation, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; object[] parameters) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new NotImplementedException(); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;H3&gt;What we’ve implemented:&lt;/H3&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&lt;B&gt;CurrentDataSource&lt;/B&gt;&lt;/FONT&gt; holds a reference to the current &lt;FONT face="Courier New"&gt;&lt;B&gt;ProductsContext&lt;/B&gt;&lt;/FONT&gt; in _&lt;FONT face="Courier New"&gt;&lt;B&gt;currentDataSource&lt;/B&gt;&lt;/FONT&gt;.&lt;/P&gt;
&lt;P&gt;Next in &lt;FONT face="Courier New"&gt;&lt;B&gt;GetQueryRootForResourceSet()&lt;/B&gt;&lt;/FONT&gt; we delegate to &lt;FONT face="Courier New"&gt;&lt;B&gt;_currentDataSource.GetQueryable()&lt;/B&gt;&lt;/FONT&gt; to find the &lt;FONT face="Courier New"&gt;&lt;B&gt;IQueryable&lt;/B&gt;&lt;/FONT&gt; for the specified &lt;FONT face="Courier New"&gt;&lt;B&gt;ResourceSet&lt;/B&gt;&lt;/FONT&gt;. &lt;BR&gt;&lt;BR&gt;We implement &lt;FONT face="Courier New"&gt;&lt;B&gt;GetResourceType(object)&lt;/B&gt;&lt;/FONT&gt;, by getting the CLR type of the current object and looking in our &lt;FONT face="Courier New"&gt;&lt;B&gt;IDataServiceMetadataProvider.Types&lt;/B&gt;&lt;/FONT&gt; to find the the one with a matching &lt;B&gt;&lt;FONT face="Courier New"&gt;InstanceType&lt;/FONT&gt;&lt;/B&gt;.&lt;/P&gt;
&lt;P&gt;Finally we return true from &lt;FONT face="Courier New"&gt;&lt;B&gt;IsNullPropagationRequired&lt;/B&gt;&lt;/FONT&gt;, because we need Data Services to compensate for the lack of NullPropagation in LINQ to Objects.&lt;/P&gt;
&lt;H4&gt;NullPropagation?&lt;/H4&gt;
&lt;P&gt;If you take a LINQ query like this:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;var results = from x in queryRoot &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; select x.Customer.Name;&lt;/FONT&gt; &lt;BR&gt;&lt;BR&gt;This could easily throw a &lt;FONT face="Courier New"&gt;&lt;B&gt;NullReferenceException&lt;/B&gt;&lt;/FONT&gt;, if &lt;FONT face="Courier New"&gt;&lt;B&gt;x.Customer&lt;/B&gt;&lt;/FONT&gt; is ever null.&lt;/P&gt;
&lt;P&gt;To avoid this Data Services can inject null checks (aka inject NullPropagation logic) into the query. All you need to do is return true from &lt;FONT face="Courier New"&gt;&lt;B&gt;IsNullPropagationRequired&lt;/B&gt;&lt;/FONT&gt;.&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#808080&gt;&lt;B&gt;NOTE:&lt;/B&gt; some IQueryables like L2S and L2E send queries to database which seamlessly support null propagation. Hence the option.&lt;/FONT&gt;&lt;/P&gt;
&lt;H3&gt;What we didn’t implement:&lt;/H3&gt;
&lt;P&gt;Our Data Service Provider is strongly typed, so Data Services will never call GetPropertyValue, because it knows how to get a property values directly from the resource object.&lt;/P&gt;
&lt;P&gt;The model we expose from our Data Service doesn’t have any ServiceOperations or OpenTypes with OpenProperties so we can safely throw NotImplemented Exception from all of those methods.&lt;/P&gt;
&lt;H3&gt;Conclusion:&lt;/H3&gt;
&lt;P&gt;Finally we have a complete Read/Only data service up an running&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/CreatingaDataServiceProviderPart5Query_E905/ROTypedService.png" mce_href="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/CreatingaDataServiceProviderPart5Query_E905/ROTypedService.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title=ROTypedService border=0 alt=ROTypedService src="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/CreatingaDataServiceProviderPart5Query_E905/ROTypedService_thumb.png" width=186 height=244 mce_src="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/CreatingaDataServiceProviderPart5Query_E905/ROTypedService_thumb.png"&gt;&lt;/A&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;We’ve got a long way to go though. We still need to add support for Update, Relationships, Service Operations, Streaming, Paging and Open Types and I want to show you how to do this all without backing CLR types too.&lt;/P&gt;
&lt;P&gt;In &lt;A href="http://blogs.msdn.com/alexj/archive/2010/01/25/creating-a-data-service-provider-part-6-query-interactions.aspx" mce_href="http://blogs.msdn.com/alexj/archive/2010/01/25/creating-a-data-service-provider-part-6-query-interactions.aspx"&gt;Part 6&lt;/A&gt; we’ll talk a little about the interaction between Data Services and your Customer Data Service Provider during a typical GET request.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9950612" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Samples/">Samples</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Astoria/">Astoria</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Data+Services/">Data Services</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/DSP/">DSP</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Walkthru/">Walkthru</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/IDataServiceQueryProvider/">IDataServiceQueryProvider</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/StronglyTyped/">StronglyTyped</category></item><item><title>Tip 50 – How to query a Data Service using JQuery</title><link>http://blogs.msdn.com/b/alexj/archive/2010/01/18/tip-50-how-to-query-a-data-service-using-jquery.aspx</link><pubDate>Mon, 18 Jan 2010 19:23:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9949932</guid><dc:creator>Alex D James</dc:creator><slash:comments>6</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/alexj/rsscomments.aspx?WeblogPostID=9949932</wfw:commentRss><comments>http://blogs.msdn.com/b/alexj/archive/2010/01/18/tip-50-how-to-query-a-data-service-using-jquery.aspx#comments</comments><description>&lt;P&gt;Recently I’ve been spending some of my time playing with &lt;A href="http://jquery.com/" mce_href="http://jquery.com/"&gt;JQuery&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;And because Data Services can expose data in JSON format, I thought I’d use JQuery to grab some data from a Data Service. &lt;/P&gt;
&lt;P&gt;Turns out it is pretty simple.&lt;/P&gt;
&lt;P&gt;This example isn’t going to win any beauty awards, but it will show you the basics and help you get started.&lt;/P&gt;
&lt;H3&gt;HTML:&lt;/H3&gt;
&lt;P&gt;First I put together this page:&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#0000ff face="Courier New"&gt;&amp;lt;html xmlns="http://www.w3.org/1999/xhtml"&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp; &amp;lt;head&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;title&amp;gt;&amp;lt;/title&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp; &amp;lt;/head&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp; &amp;lt;script src="Scripts/jquery-1.3.2.js" type="text/javascript"&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp; &amp;lt;/script&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp; &amp;lt;script type="text/javascript"&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp; &lt;FONT color=#008000&gt;// JSON CODE IS GOING TO GO HERE&lt;/FONT&gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp; &amp;lt;/script&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp; &amp;lt;body&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;a href='#' id="aShowProducts"&amp;gt;Show Products&amp;lt;/a&amp;gt;&amp;lt;br /&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;a href='#' id="aShowCategories"&amp;gt;Show Categories&amp;lt;/a&amp;gt;&amp;lt;br /&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;div id="divResults" /&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp; &amp;lt;/body&amp;gt; &lt;BR&gt;&amp;lt;/html&amp;gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;As you can see it is trivial.&lt;/P&gt;
&lt;H3&gt;JQuery Code&lt;/H3&gt;
&lt;P&gt;Next comes the JQuery code.&lt;/P&gt;
&lt;P&gt;The first step as always with JQuery is to hook up some document ready code:&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#0000ff face="Courier New"&gt;var divResults; &lt;BR&gt;var aShowProducts; &lt;BR&gt;var aShowCategories; &lt;BR&gt;var ajaxRequest; &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#0000ff face="Courier New"&gt;$(document).ready(function () { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; divResults = $('#divResults'); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; aShowCategories = $('#aShowCategories'); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; aShowProducts = $('#aShowProducts'); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; aShowProducts.click(function () { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GetData('Products'); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; aShowCategories.click(function () { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GetData('Categories'); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }); &lt;BR&gt;});&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;When the document is ready first I grab hold of some globals:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;divResults&lt;/STRONG&gt; (i.e. &lt;FONT color=#0000ff face="Courier New"&gt;&amp;lt;div id=”divResults” /&amp;gt;&lt;/FONT&gt;): to hold the results of our query. &lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;aShowProducts&lt;/STRONG&gt; (i.e. &lt;FONT color=#0000ff face="Courier New"&gt;&amp;lt;a href=”#” id=”aShowProducts” …&amp;lt;/a&amp;gt;&lt;/FONT&gt;): the ‘Show Products’ link. &lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;aShowCategory&lt;/STRONG&gt;: the ‘Show Categories’ hyperlink. &lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;ajaxRequest&lt;/STRONG&gt;: is a variable for holding onto the current ‘request’ so we can abort it if necessary. &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Then I hook up the GetData method to the click event of the two hyperlinks, passing in the appropriate Data Service resource set name.&lt;/P&gt;
&lt;H3&gt;Getting Results&lt;/H3&gt;
&lt;P&gt;The GetData function looks like this:&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#0000ff face="Courier New"&gt;function GetData(set) { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var materializer; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; switch (set) { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; case 'Categories': &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; materializer = GetRowForCategory; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; case 'Products': &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; materializer = GetRowForProduct; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; default: &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; alert('problems'); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/P&gt;&lt;FONT color=#0000ff face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (ajaxRequest!= null) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ajaxRequest.abort(); &lt;/FONT&gt;
&lt;P&gt;&lt;FONT color=#0000ff face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ajaxRequest= $.getJSON( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "ProductsService.svc/" + set, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; function (data) { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var array = []; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; array.push("&amp;lt;table&amp;gt;"); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $.each(data.d, function (i, item) { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; materializer(array, item) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; array.push("&amp;lt;/table&amp;gt;"); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; divResults.html(array.join("")); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ); &lt;BR&gt;} &lt;BR&gt;&lt;/FONT&gt;&lt;BR&gt;What this does is based on the ‘set’ argument it chooses a function to use as the materializer, i.e. the function that will produce a &amp;lt;tr&amp;gt; for the corresponding resource type.&lt;/P&gt;
&lt;P&gt;So for the ‘Categories’ set I use this function:&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#0000ff face="Courier New"&gt;function GetRowForCategory(array, item) &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; array.push("&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;"); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; array.push(item.Id); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; array.push("&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;"); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; array.push(item.Name); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; array.push("&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;"); &lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;And for the ‘Products’ set this:&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#0000ff face="Courier New"&gt;function GetRowForProduct(array,item) &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; array.push("&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;"); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; array.push(item.Id); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; array.push("&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;"); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; array.push(item.Name); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; array.push("&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;"); &lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Once we’ve chosen the correct materializer next we abort any in progress AJAX requests.&lt;/P&gt;
&lt;P&gt;And initiate a new AJAX request using &lt;FONT color=#0000ff face="Courier New"&gt;$.getJSON(…)&lt;/FONT&gt; to get JSON from either &lt;FONT face="Courier New"&gt;"ProductsService.svc/Products"&lt;/FONT&gt; or&lt;FONT face="Courier New"&gt; "ProductsService.svc/Categories"&lt;/FONT&gt;.&lt;/P&gt;
&lt;P&gt;The resulting JSON (i.e. data) is passed to my callback function that builds some html for a table by:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;using the &lt;FONT color=#0000ff face="Courier New"&gt;array.push(…)&lt;/FONT&gt; approach to build the html string. &lt;/LI&gt;
&lt;LI&gt;and &lt;FONT color=#0000ff face="Courier New"&gt;$.each(data.d)&lt;/FONT&gt; to enumerate over the entities and call the specified materializer for each entity to create a new &lt;FONT color=#0000ff face="Courier New"&gt;&amp;lt;tr /&amp;gt;&lt;/FONT&gt; &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Finally I insert the html – &lt;FONT color=#0000ff face="Courier New"&gt;array.join("")&lt;/FONT&gt; – into the div.&lt;/P&gt;
&lt;H3&gt;Trying it out for yourself&lt;/H3&gt;
&lt;P&gt;You can &lt;STRONG&gt;Save As&lt;/STRONG&gt; the &lt;A href="http://blogs.msdn.com/alexj/attachment/9949932.ashx" mce_href="http://blogs.msdn.com/alexj/attachment/9949932.ashx"&gt;complete html&lt;/A&gt;&amp;nbsp;here.&lt;/P&gt;
&lt;P&gt;All you need to do is drop the html file in the same website as your DataService change the url to point to your DataService and modify the materializer chooser code and the materializers themselves to match your ResourceSets and ResourceTypes.&lt;/P&gt;
&lt;P&gt;Not too hard.&lt;/P&gt;
&lt;P&gt;The next step would be to experiment with something to build more interesting queries, see &lt;A href="http://blogs.msdn.com/alexj/archive/2009/11/18/tip-44-how-to-navigate-an-odata-compliant-service.aspx" mce_href="http://blogs.msdn.com/alexj/archive/2009/11/18/tip-44-how-to-navigate-an-odata-compliant-service.aspx"&gt;Tip 44&lt;/A&gt; for some ideas.&lt;/P&gt;
&lt;P&gt;Oh an BTW I’m new to JQuery so if you spot a newbie mistake please let me know.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9949932" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-09-94-99-32/Tip50.htm" length="2276" type="text/html" /><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Tips/">Tips</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Data+Services/">Data Services</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/JSON/">JSON</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/JQuery/">JQuery</category></item><item><title>Creating a Data Service Provider – Part 4 – Minimal Running Service</title><link>http://blogs.msdn.com/b/alexj/archive/2010/01/15/creating-a-data-service-provider-part-4-minimal-running-service.aspx</link><pubDate>Fri, 15 Jan 2010 00:01:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9948713</guid><dc:creator>Alex D James</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/alexj/rsscomments.aspx?WeblogPostID=9948713</wfw:commentRss><comments>http://blogs.msdn.com/b/alexj/archive/2010/01/15/creating-a-data-service-provider-part-4-minimal-running-service.aspx#comments</comments><description>&lt;P&gt;This is Part 4 of my &lt;A href="http://blogs.msdn.com/alexj/archive/2010/01/07/data-service-providers-getting-started.aspx" mce_href="http://blogs.msdn.com/alexj/archive/2010/01/07/data-service-providers-getting-started.aspx"&gt;ongoing series of posts showing how to create an Custom Data Service Provider&lt;/A&gt;. &lt;BR&gt;&lt;B&gt;&lt;BR&gt;&lt;FONT color=#808080&gt;NOTE:&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#808080&gt; I’ve done a little refactoring to the code in &lt;/FONT&gt;&lt;A href="http://blogs.msdn.com/alexj/archive/2010/01/08/creating-a-data-service-provider-part-3-metadata.aspx" mce_href="http://blogs.msdn.com/alexj/archive/2010/01/08/creating-a-data-service-provider-part-3-metadata.aspx"&gt;&lt;FONT color=#808080&gt;Part 3&lt;/FONT&gt;&lt;/A&gt;&lt;FONT color=#808080&gt; to simplify the code in this post, so be sure to check that out if you’ve been following along.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;In &lt;A href="http://blogs.msdn.com/alexj/archive/2010/01/07/creating-a-data-service-provider-part-2-iserviceprovider-datasources.aspx" mce_href="http://blogs.msdn.com/alexj/archive/2010/01/07/creating-a-data-service-provider-part-2-iserviceprovider-datasources.aspx"&gt;Parts 2&lt;/A&gt; &amp;amp; &lt;A href="http://blogs.msdn.com/alexj/archive/2010/01/08/creating-a-data-service-provider-part-3-metadata.aspx" mce_href="http://blogs.msdn.com/alexj/archive/2010/01/08/creating-a-data-service-provider-part-3-metadata.aspx"&gt;3&lt;/A&gt;&amp;nbsp; we hooked up our implementation of &lt;A href="http://msdn.microsoft.com/en-us/library/system.iserviceprovider.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.iserviceprovider.aspx"&gt;IServiceProvider&lt;/A&gt; and &lt;A href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataservicemetadataprovider%28VS.100%29.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataservicemetadataprovider(VS.100).aspx"&gt;IDataServiceMetadataProvider&lt;/A&gt;. &lt;/P&gt;
&lt;H3&gt;Exposing IDataServiceQueryProvider&lt;/H3&gt;
&lt;P&gt;Now we need to implement &lt;A href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataservicequeryprovider%28VS.100%29.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataservicequeryprovider(VS.100).aspx"&gt;IDataServiceQueryProvider&lt;/A&gt;, and &lt;B&gt;&lt;FONT color=#008000&gt;refactor&lt;/FONT&gt;&lt;/B&gt; our &lt;A href="http://msdn.microsoft.com/en-us/library/system.iserviceprovider.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.iserviceprovider.aspx"&gt;IServiceProvider&lt;/A&gt; implementation to expose it:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;public abstract class DSPDataService&amp;lt;T&amp;gt; : &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DataService&amp;lt;T&amp;gt;, IServiceProvider &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IDataServiceMetadataProvider _metadata; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;B&gt;&lt;FONT color=#008000&gt;public IDataServiceQueryProvider _query;&lt;/FONT&gt;&lt;/B&gt; &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public DSPDataService() &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _metadata = GetMetadataProvider(typeof(T)); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;B&gt;&lt;FONT color=#008000&gt;_query = GetQueryProvider(_metadata);&lt;/FONT&gt;&lt;/B&gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public object GetService(Type serviceType) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (serviceType == typeof(IDataServiceMetadataProvider)) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return _metadata; &lt;BR&gt;&lt;FONT color=#0000ff&gt;&lt;B&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;FONT color=#008000&gt;else if (serviceType == typeof(IDataServiceQueryProvider)) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return _query;&lt;/FONT&gt;&lt;/B&gt;&lt;/FONT&gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return null; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public abstract IDataServiceMetadataProvider &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GetMetadataProvider(Type dataSourceType); &lt;BR&gt;&lt;BR&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#008000&gt;public abstract IDataServiceQueryProvider&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GetQueryProvider(IDataServiceMetadataProvider metadata);&lt;/FONT&gt; &lt;/B&gt;&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Notice there is a new GetQueryProvider(…) method that your DataService must override.&lt;/P&gt;
&lt;P&gt;The IDataServiceMetadataProvider might be needed by the IDataServiceQueryProvider so it is passed as an argument.&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;public class Sample : DSPDataService&amp;lt;object&amp;gt; &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;A href="http://blogs.msdn.com/alexj/archive/2010/01/08/creating-a-data-service-provider-part-3-metadata.aspx" mce_href="http://blogs.msdn.com/alexj/archive/2010/01/08/creating-a-data-service-provider-part-3-metadata.aspx"&gt;… see part 3 for the rest of code …&lt;/A&gt; &lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;BR&gt;&lt;B&gt;&lt;FONT color=#008000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public override IDataServiceQueryProvider &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GetQueryProvider(IDataServiceMetadataProvider metadata) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return new DSPQueryProvider&amp;lt;object&amp;gt;(); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/B&gt; &lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;H3&gt;Implementing IDataServiceQueryProvider&lt;/H3&gt;
&lt;P&gt;If you only want to be able to see the ServiceDoc and $metadata you only need to implement the CurrentDataSource property, the rest of the methods are only called when you actually query one of the ResourceSets: &lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;public class DSPQueryProvider&amp;lt;T&amp;gt; : IDataServiceQueryProvider &lt;BR&gt;{&amp;nbsp; &lt;BR&gt;&lt;B&gt;&lt;FONT color=#008000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; T_currentDataSource; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public object CurrentDataSource &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return _currentDataSource; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; set { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _currentDataSource= value as T; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/B&gt;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public object GetOpenPropertyValue( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; object target, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string propertyName) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new NotImplementedException(); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IEnumerable&amp;lt;KeyValuePair&amp;lt;string, object&amp;gt;&amp;gt;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GetOpenPropertyValues(object target) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new NotImplementedException(); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public object GetPropertyValue( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; object target, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ResourceProperty resourceProperty) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new NotImplementedException(); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IQueryable GetQueryRootForResourceSet( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ResourceSet resourceSet) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new NotImplementedException(); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public ResourceType GetResourceType(object target) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new NotImplementedException(); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public object InvokeServiceOperation( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ServiceOperation serviceOperation, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; object[] parameters) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new NotImplementedException(); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public bool IsNullPropagationRequired &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get { throw new NotImplementedException(); } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;We’ve now done the minimum you possible can to get a custom Data Service Provider based Service actually running!&lt;/P&gt;
&lt;P&gt;If you browse to your &lt;B&gt;http://localhost/sample.svc&lt;/B&gt; now you will see something like this:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/CreatingaDataServiceProviderPart4Query_A187/ServiceDoc.png" mce_href="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/CreatingaDataServiceProviderPart4Query_A187/ServiceDoc.png"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=ServiceDoc border=0 alt=ServiceDoc src="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/CreatingaDataServiceProviderPart4Query_A187/ServiceDoc_thumb.png" width=244 height=165 mce_src="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/CreatingaDataServiceProviderPart4Query_A187/ServiceDoc_thumb.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;And this &lt;B&gt;http://localhost/sample.svc/$metadata &lt;/B&gt;should look like this:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/CreatingaDataServiceProviderPart4Query_A187/DollarMetadata.png" mce_href="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/CreatingaDataServiceProviderPart4Query_A187/DollarMetadata.png"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=DollarMetadata border=0 alt=DollarMetadata src="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/CreatingaDataServiceProviderPart4Query_A187/DollarMetadata_thumb.png" width=244 height=200 mce_src="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/CreatingaDataServiceProviderPart4Query_A187/DollarMetadata_thumb.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;But if you navigate to the Products ResourceSet you will get an error:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/CreatingaDataServiceProviderPart4Query_A187/Error.png" mce_href="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/CreatingaDataServiceProviderPart4Query_A187/Error.png"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=Error border=0 alt=Error src="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/CreatingaDataServiceProviderPart4Query_A187/Error_thumb.png" width=244 height=111 mce_src="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/CreatingaDataServiceProviderPart4Query_A187/Error_thumb.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;That’s because of all those NotImplementedExceptions.&lt;/P&gt;
&lt;P&gt;In &lt;A href="http://blogs.msdn.com/alexj/archive/2010/01/19/creating-a-data-service-provider-part-5-query.aspx" mce_href="http://blogs.msdn.com/alexj/archive/2010/01/19/creating-a-data-service-provider-part-5-query.aspx"&gt;Part 5&lt;/A&gt; we will flesh out our implementation so query works too...&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9948713" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Astoria/">Astoria</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Data+Services/">Data Services</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/DSP/">DSP</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Walkthru/">Walkthru</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/IDataServiceMetadataProvider/">IDataServiceMetadataProvider</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/IDataServiceQueryProvider/">IDataServiceQueryProvider</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/IServiceProvider/">IServiceProvider</category></item><item><title>Creating a Data Service Provider – Part 3 - IDataServiceMetadataProvider</title><link>http://blogs.msdn.com/b/alexj/archive/2010/01/08/creating-a-data-service-provider-part-3-metadata.aspx</link><pubDate>Fri, 08 Jan 2010 01:52:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9945498</guid><dc:creator>Alex D James</dc:creator><slash:comments>10</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/alexj/rsscomments.aspx?WeblogPostID=9945498</wfw:commentRss><comments>http://blogs.msdn.com/b/alexj/archive/2010/01/08/creating-a-data-service-provider-part-3-metadata.aspx#comments</comments><description>&lt;p mce_keep="true"&gt;&lt;font color="#808080"&gt;&lt;b&gt;UPDATE:&lt;/b&gt; I’ve made a few updates to the code / write-up to reflect refactors I’ve made as I’ve implemented more of the interfaces.&lt;/font&gt;&lt;/p&gt;
&lt;p mce_keep="true"&gt;This is Part 3 of &lt;a href="http://blogs.msdn.com/alexj/archive/2010/01/07/data-service-providers-getting-started.aspx" mce_href="http://blogs.msdn.com/alexj/archive/2010/01/07/data-service-providers-getting-started.aspx"&gt;my ongoing series on Creating a Data Service Provider&lt;/a&gt;, and in this post we’ll look at how to implement &lt;a href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataservicemetadataprovider%28VS.100%29.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataservicemetadataprovider(VS.100).aspx"&gt;&lt;b&gt;IDataServiceMetadataProvider&lt;/b&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;IDataServiceMetadataProvider is responsible for describing the shape of the Resources and ResourceSets available from your DataSource (see &lt;a href="http://blogs.msdn.com/alexj/archive/2010/01/07/creating-a-data-service-provider-part-2-iserviceprovider-datasources.aspx" mce_href="http://blogs.msdn.com/alexj/archive/2010/01/07/creating-a-data-service-provider-part-2-iserviceprovider-datasources.aspx"&gt;Part 2&lt;/a&gt;). &lt;br&gt;&lt;br&gt;And what is available from your DataSource is really up to you: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;It could be completely static.&lt;/b&gt; For example if you are exposing data from an off the shelve software package or something where the model is fixed – perhaps Twitter, Stackoverflow or something similar. &lt;/li&gt;
&lt;li&gt;&lt;b&gt;It could be strongly typed.&lt;/b&gt; For example your implementation might reflect over the Properties of the DataSource itself and create ResourceSets for each property that returns IQueryable&amp;lt;T&amp;gt; and ResourceTypes for all Ts. This is essentially the way the built-in Reflection and Entity Framework providers work. &lt;/li&gt;
&lt;li&gt;&lt;b&gt;It could be completely dynamic.&lt;/b&gt; For example you could go off to some database somewhere and read a catalog. &lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Your options are almost endless. &lt;/p&gt;
&lt;p&gt;However whichever option you chose the first step is to create a class that implements the interface.&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;public class DSPMetadata: IDataServiceMetadataProvider &lt;br&gt;{&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;The interface has 6 methods and 5 properties, which sounds terribly complicated until you actually try to implement it. I got my first example working in less than half an hour, and I’m not even a developer anymore!&lt;/p&gt;
&lt;p&gt;Here is how I’ve hooked it together:&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;public abstract class DSPDataService&amp;lt;T&amp;gt;: DataService&amp;lt;T&amp;gt; &lt;br&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;{&amp;nbsp; &lt;br&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp; IDataServiceMetadataProvider _metadata; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp; public DSPMetadata() &lt;br&gt;&amp;nbsp;&amp;nbsp; { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _metadata = GetMetadataProvider(typeof(T)); &lt;br&gt;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp; public object GetService(Type serviceType) &lt;br&gt;&amp;nbsp;&amp;nbsp; { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (serviceType == typeof(IDataServiceMetadataProvider)) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return _metadata; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; …&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp; }&amp;nbsp; &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp; public abstract IDataServiceMetadataProvider GetMetadataProvider(Type dataSourceType); &lt;br&gt;}&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;As you can see this code has an abstract method to get the actual metadata, which subclasses must implement. &lt;/p&gt;
&lt;p&gt;We are almost ready to implement the interface, but first lets learn about…&lt;/p&gt;
&lt;h3&gt;Creating Metadata&lt;/h3&gt;
&lt;p&gt;If you look at the methods on the interface you will see &lt;a href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.resourcetype%28VS.100%29.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.resourcetype(VS.100).aspx"&gt;ResourceTypes&lt;/a&gt;, &lt;a href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.resourceproperty%28VS.100%29.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.resourceproperty(VS.100).aspx"&gt;ResourceProperties&lt;/a&gt;, &lt;a href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.serviceoperation%28VS.100%29.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.serviceoperation(VS.100).aspx"&gt;ServiceOperations&lt;/a&gt;, &lt;a href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.resourceset%28VS.100%29.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.resourceset(VS.100).aspx"&gt;ResourceSets&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.resourceassociationset%28VS.100%29.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.resourceassociationset(VS.100).aspx"&gt;ResourceAssociationSets&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;These are the public classes in the System.Data.Services assembly that you can construct and manipulate yourself to describe your model. &lt;/p&gt;
&lt;p&gt;Essentially these methods just walk over this metadata, exposing different information about the model.&lt;/p&gt;
&lt;p&gt;Imagine if you have this CLR class:&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;public class Product &lt;br&gt;{ &lt;br&gt;&amp;nbsp;&amp;nbsp; public int ProdKey {get;set;} &lt;br&gt;&amp;nbsp;&amp;nbsp; public string Name {get;set;} &lt;br&gt;&amp;nbsp;&amp;nbsp; public Decimal Price {get;set;} &lt;br&gt;&amp;nbsp;&amp;nbsp; public Decimal Cost {get;set;}&lt;/font&gt;&lt;font face="Courier New"&gt; &lt;br&gt;}&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;And you want to create a ResourceType for Product, this is how you would do it:&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;var productType = new ResourceType( &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; typeof(Product), // CLR type backing this Resource &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ResourceTypeKind.EntityType, // Entity, ComplexType etc &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; null, // BaseType &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Namespace", // Namespace &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Product", // Name &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; false // Abstract? &lt;br&gt;); &lt;br&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;var prodKey = new ResourceProperty( &lt;br&gt;&amp;nbsp;&amp;nbsp; "ProdKey", &lt;br&gt;&amp;nbsp;&amp;nbsp; ResourcePropertyKind.Key | &lt;br&gt;&amp;nbsp;&amp;nbsp; ResourcePropertyKind.Primitive, &lt;br&gt;&amp;nbsp;&amp;nbsp; ResourceType.GetPrimitiveResourceType(typeof(int)) &lt;br&gt;); &lt;br&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;var prodName = new ResourceProperty( &lt;br&gt;&amp;nbsp;&amp;nbsp; "Name",&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp; ResourcePropertyKind.Primitive, &lt;br&gt;&amp;nbsp;&amp;nbsp; ResourceType.GetPrimitiveResourceType(typeof(string)) &lt;br&gt;); &lt;br&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;var prodPrice = new ResourceProperty( &lt;br&gt;&amp;nbsp;&amp;nbsp; "Price",&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp; ResourcePropertyKind.Primitive, &lt;br&gt;&amp;nbsp;&amp;nbsp; ResourceType.GetPrimitiveResourceType(typeof(Decimal)) &lt;br&gt;); &lt;br&gt;productType.AddProperty(prodKey); &lt;br&gt;productType.AddProperty(prodName); &lt;br&gt;productType.AddProperty(prodPrice);&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;Notice that we aren’t exposing the Cost property, because that is ‘sensitive’ information.&lt;/p&gt;
&lt;p&gt;Next to create a ResourceSet called Products to expose our ResourceType, you simply do this:&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;var productsSet = new ResourceSet("Products", productType);&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;As you can see building metadata is not hard. &lt;/p&gt;
&lt;h3&gt;Freezing your metadata&lt;/h3&gt;
&lt;p&gt;The final step before you can use the Metadata is to freeze it:&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;productsSet.SetReadonly(); &lt;br&gt;productType.SetReadonly();&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;This means it can no longer be modified, at least not for the current Request.&lt;/p&gt;
&lt;p&gt;&lt;font color="#808080"&gt;&lt;b&gt;NOTE:&lt;/b&gt; Data Services will ask for a IDataServiceMetadataProvider implementation for every request so even though you need to Freeze your metadata per-request, it is completely possible to reconstruct the metadata for each request if necessary.&lt;/font&gt;&lt;/p&gt;
&lt;h3&gt;Exposing Metadata via IDataServiceMetadataProvider&lt;/h3&gt;
&lt;p&gt;Once you’ve built your metadata you just need to expose it via your implementation.&lt;/p&gt;
&lt;p&gt;Here is what your implementation might look like if you didn’t support inheritance, relationships or service operations.&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;public class DSPMetadataProvider &lt;br&gt;{&amp;nbsp; &lt;br&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private Dictionary&amp;lt;string, ResourceType&amp;gt; _resourceTypes&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = new Dictionary&amp;lt;string, ResourceType&amp;gt;(); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private Dictionary&amp;lt;string, ResourceSet&amp;gt; _resourceSets &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = new Dictionary&amp;lt;string, ResourceSet&amp;gt;(); &lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public DSPMetadataProvider(){}&lt;/font&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void AddResourceType(ResourceType type) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; type.SetReadOnly(); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _resourceTypes.Add(type.FullName, type); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void AddResourceSet(ResourceSet set) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; set.SetReadOnly(); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _resourceSets.Add(set.Name, set); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string ContainerName &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get { return "Container"; } &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp; &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string ContainerNamespace &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get { return "Namespace"; } &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IEnumerable&amp;lt;ResourceType&amp;gt; GetDerivedTypes( &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ResourceType resourceType &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // We don't support type inheritance yet &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; yield break; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp; &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public ResourceAssociationSet GetResourceAssociationSet( &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ResourceSet resourceSet, &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ResourceType resourceType, &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ResourceProperty resourceProperty) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new NotImplementedException("No relationships."); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp; &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public bool HasDerivedTypes(ResourceType resourceType) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // We don’t support inheritance yet &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return false; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IEnumerable&amp;lt;ResourceSet&amp;gt; ResourceSets &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get { return this.resourceSets.Values; } &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp; &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IEnumerable&amp;lt;ServiceOperation&amp;gt; ServiceOperations &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // No service operations yet &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get { yield break; } &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp; &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public bool TryResolveResourceSet( &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string name, &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; out ResourceSet resourceSet) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return resourceSets.TryGetValue(name, out resourceSet); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp; &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public bool TryResolveResourceType( &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string name,&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; out ResourceType resourceType) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return resourceTypes.TryGetValue(name, out resourceType); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public bool TryResolveServiceOperation( &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string name,&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; out ServiceOperation serviceOperation) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // No service operations are supported yet &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; serviceOperation = null; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return false; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp; &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IEnumerable&amp;lt;ResourceType&amp;gt; Types &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get { return this.resourceTypes.Values; } &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;}&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;The idea here is that your implementation of GetMetadataProvider you do something like this:&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;public override IDataServiceMetadataProvider GetMetadataProvider(Type dataSourceType) &lt;br&gt;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DSPMetadataProvider metadata = new DSPMetadataProvider(); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var productType = new ResourceType( &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; typeof(Product), // CLR type backing this Resource &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ResourceTypeKind.EntityType, // Entity, ComplexType etc &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; null, // BaseType &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Namespace", // Namespace &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Product", // Name &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; false // Abstract? &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var prodKey = new ResourceProperty( &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "ProdKey", &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ResourcePropertyKind.Key | &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ResourcePropertyKind.Primitive, &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ResourceType.GetPrimitiveResourceType(typeof(int)) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var prodName = new ResourceProperty( &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Name", &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ResourcePropertyKind.Primitive, &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ResourceType.GetPrimitiveResourceType(typeof(string)) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var prodPrice = new ResourceProperty( &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Price", &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ResourcePropertyKind.Primitive, &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ResourceType.GetPrimitiveResourceType(typeof(Decimal)) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; productType.AddProperty(prodKey); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; productType.AddProperty(prodName); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; productType.AddProperty(prodPrice); &lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; metadata.AddResourceType(productType); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; metadata.AddResourceSet( &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new ResourceSet("Products", productType) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return metadata; &lt;br&gt;}&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;Notice that as you add ResourceTypes and ResourceSets to the metadata they are indexed and frozen (SetReadOnly) for you. &lt;br&gt;&lt;br&gt;Of course as you add support for inheritance, relationships and service operations, things get a little bit more complicated. But you can handle each of these methods using LINQ to Objects pretty easily.&lt;/p&gt;
&lt;h3&gt;Performance Considerations&lt;/h3&gt;
&lt;p&gt;You might have noticed that there are two kinds of functions/properties on this interface, those that return enumerations and those that try to find a specific instance. &lt;br&gt;&lt;br&gt;This is for performance reasons.&lt;/p&gt;
&lt;p&gt;Most requests to the server use the TryResolveXXX instance methods. This means that even if you have a lot of metadata you can often avoid creating most of it. &lt;br&gt;&lt;br&gt;The other methods are called much more sparingly: for example when someone gets $metadata or the root service document.&lt;/p&gt;
&lt;h3&gt;Next time&lt;/h3&gt;
&lt;p&gt;Now we’ve implemented hooked up our DataService to our Custom DSP, and we’ve implemented &lt;a href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataservicemetadataprovider%28VS.100%29.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataservicemetadataprovider(VS.100).aspx"&gt;IDataServiceMetadataProvider&lt;/a&gt;, all we need to do to finish our custom read-only DSP is implement &lt;a href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataservicequeryprovider%28VS.100%29.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataservicequeryprovider(VS.100).aspx"&gt;IDataServiceQueryProvider&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;We’ll start to cover that in &lt;a href="http://blogs.msdn.com/alexj/archive/2010/01/15/creating-a-data-service-provider-part-4-minimal-running-service.aspx" mce_href="http://blogs.msdn.com/alexj/archive/2010/01/15/creating-a-data-service-provider-part-4-minimal-running-service.aspx"&gt;Part 4&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9945498" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Samples/">Samples</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Data+Services/">Data Services</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/DSP/">DSP</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/IDataServiceMetadataProvider/">IDataServiceMetadataProvider</category></item><item><title>Custom Data Service Providers</title><link>http://blogs.msdn.com/b/alexj/archive/2010/01/07/data-service-providers-getting-started.aspx</link><pubDate>Thu, 07 Jan 2010 22:33:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9945444</guid><dc:creator>Alex D James</dc:creator><slash:comments>11</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/alexj/rsscomments.aspx?WeblogPostID=9945444</wfw:commentRss><comments>http://blogs.msdn.com/b/alexj/archive/2010/01/07/data-service-providers-getting-started.aspx#comments</comments><description>&lt;h3&gt;Introduction&lt;/h3&gt;
&lt;p&gt;Data Services sits above a Data Service Provider, which is responsible for interacting with the underlying Data Source on behalf of the Data Service.&lt;/p&gt;
&lt;p&gt;Data Services ships with some internal providers, and makes it possible for you to create custom providers too.&lt;/p&gt;
&lt;p&gt;So the obvious question is...&lt;/p&gt;
&lt;h3&gt;Do you need a Custom Data Provider?&lt;/h3&gt;
&lt;p&gt;Creating a Custom Data Service Provider is a fair amount of work, which of course provides big dividends like, allowing people to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Query and manipulate your data via the Data Services Client in:
&lt;ul&gt;
&lt;li&gt;WPF&lt;/li&gt;
&lt;li&gt;WinForms&lt;/li&gt;
&lt;li&gt;SilverLight &lt;/li&gt;
&lt;li&gt;etc&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Query you data directly via a browser&lt;/li&gt;
&lt;li&gt;Query and manipulate your data via Javascript and associated frameworks like JQuery&lt;/li&gt;
&lt;li&gt;Query your data via knowledge worker tools like &lt;a href="http://www.powerpivot.com/"&gt;PowerPivot&lt;/a&gt;. &lt;/li&gt;
&lt;li&gt;etc.etc.etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But before you jump into creating a custom provider, see if you fall into one of the following camps, all of which have a much easier solution:&lt;/p&gt;
&lt;h4&gt;Entity Framework&lt;/h4&gt;
&lt;p&gt;If you plan on putting a Data Service over the Entity Framework the answer is&amp;nbsp;no you don't need to write a custom provider. &lt;/p&gt;
&lt;p&gt;Data Services has an implementation that talks to the Entity Framework in the box. &lt;br /&gt;&lt;br /&gt;You simply point your DataService at your strongly typed ObjectContext, and that&amp;rsquo;s it:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New;"&gt;public class NorthwindDataService: &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DataService&amp;lt;NorthwindEntities&amp;gt;&lt;/span&gt; &lt;/p&gt;
&lt;p&gt;In this example NorthwindEntities is your strongly typed ObjectContext representing the Northwind database.&lt;/p&gt;
&lt;p&gt;For a good example of an OData Service built using the Entity Framework check out &lt;a href="http://blogs.msdn.com/b/astoriateam/archive/2009/12/17/getting-started-with-the-data-services-update-for-net-3-5-sp1-part-1.aspx"&gt;this post.&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;LINQ to SQL&lt;/h4&gt;
&lt;p&gt;If you want to create a Data Service over a LINQ to SQL data source you should take a &lt;a href="http://code.msdn.microsoft.com/IUpdateableLinqToSql"&gt;look at this project on Code Gallery&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;It includes sample code you can use to extend your strongly typed DataContext class to implement the &lt;a href="http://msdn.microsoft.com/en-us/library/system.data.services.iupdatable.aspx"&gt;IUpdatable&lt;/a&gt; interface. &lt;/p&gt;
&lt;p&gt;This in conjunction with the Reflection Provider means you can use your LINQ to SQL DataContext just like an Entity Framework ObjectContext:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New;"&gt;public class NorthwindDataService: &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DataService&amp;lt;NorthwindDataContext&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;h4&gt;Reflection Provider&lt;/h4&gt;
&lt;p&gt;If you have your own class that can represent your Data Source, and it has a number of strongly typed IQueryable properties like this:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New;"&gt;public class MyDataSource &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IQueryable&amp;lt;Product&amp;gt; Products { get {&amp;hellip;} } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IQueryable&amp;lt;Categories&amp;gt; Categories { get {&amp;hellip;} } &lt;br /&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The built-in reflection provider can turn this into a read-only service and infer ResourceSets, Types and Properties automatically.&lt;/p&gt;
&lt;p&gt;You can even make this read-write by extending your class to implement IUpdatable:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New;"&gt;public class MyDataSource: IUpdatable&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;In fact this is exactly how the LINQ to SQL example above works.&lt;/p&gt;
&lt;p&gt;For a good example of an OData Service created using the reflection provider check out &lt;a href="http://blogs.msdn.com/b/alexj/archive/2010/06/11/tip-56-writing-an-odata-service-using-the-reflection-provider.aspx"&gt;Tip 56&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;So when do you actually need a custom provider?&lt;/h3&gt;
&lt;p&gt;The reflection provider is very useful for some scenarios. &lt;br /&gt;&lt;br /&gt;But is has a number of limitations that might disqualify it for your scenario:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;It is static, i.e. the shape of the service can&amp;rsquo;t evolve over time.&lt;/li&gt;
&lt;li&gt;It needs CLR classes for each ResourceType, which you might not have.&lt;/li&gt;
&lt;li&gt;It needs to find Id or {Type}Id properties to&amp;nbsp;use as&amp;nbsp;keys.&lt;/li&gt;
&lt;li&gt;It blindly exposes all public properties of the CLR classes.&lt;/li&gt;
&lt;li&gt;It gives you less control over streaming or paging.&lt;/li&gt;
&lt;li&gt;You can&amp;rsquo;t take advantage of advanced features like Open Types, which allows resources to optionally include more &lt;a href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataservicequeryprovider.getopenpropertyvalue(VS.100).aspx"&gt;Open Properties.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;You have less control, for example you can't log requests as easily or modify metadata or rename properties &lt;/li&gt;
&lt;li&gt;etc. etc. etc.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If any of these are important it&amp;rsquo;s time to create a Custom Data Service Provider&amp;hellip;&lt;/p&gt;
&lt;h3&gt;Creating a Data Service Provider Series&lt;/h3&gt;
&lt;p&gt;This series of posts will grow to cover all of the major DSP interfaces and show case lots of scenarios&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/alexj/archive/2010/01/04/creating-a-data-service-provider-part-1-intro.aspx"&gt;Part 1 &amp;ndash; Intro&lt;/a&gt; &lt;br /&gt;&lt;a href="http://blogs.msdn.com/alexj/archive/2010/01/07/creating-a-data-service-provider-part-2-iserviceprovider-datasources.aspx"&gt;Part 2 &amp;ndash; IServiceProvider and DataSources&lt;/a&gt; &lt;br /&gt;&lt;a href="http://blogs.msdn.com/alexj/archive/2010/01/08/creating-a-data-service-provider-part-3-metadata.aspx"&gt;Part 3&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;ndash;&lt;/span&gt; IDataServiceMetadataProvider&lt;/a&gt;&amp;nbsp;&lt;br /&gt;&lt;a href="http://blogs.msdn.com/alexj/archive/2010/01/15/creating-a-data-service-provider-part-4-minimal-running-service.aspx"&gt;Part 4&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;ndash;&lt;/span&gt; Minimal Running Service&lt;/a&gt;&lt;br /&gt;&lt;a href="http://blogs.msdn.com/alexj/archive/2010/01/19/creating-a-data-service-provider-part-5-query.aspx"&gt;Part 5 &amp;ndash; Query&lt;/a&gt;&lt;br /&gt;&lt;a href="http://blogs.msdn.com/alexj/archive/2010/01/25/creating-a-data-service-provider-part-6-query-interactions.aspx"&gt;Part&amp;nbsp;6 &amp;ndash; Query Interactions&lt;/a&gt;&lt;br /&gt;&lt;a href="http://blogs.msdn.com/alexj/archive/2010/02/11/creating-a-data-service-provider-part-7-update.aspx"&gt;Part&amp;nbsp;7 &amp;ndash; Updates&lt;br /&gt;&lt;/a&gt;&lt;a href="http://blogs.msdn.com/alexj/archive/2010/02/24/creating-a-data-service-provider-part-8-relationships.aspx"&gt;Part 8 - Relationships&lt;/a&gt;&lt;a href="http://blogs.msdn.com/alexj/archive/2010/02/11/creating-a-data-service-provider-part-7-update.aspx"&gt; &lt;/a&gt;&lt;br /&gt;&lt;a href="http://blogs.msdn.com/alexj/archive/2010/03/02/creating-a-data-service-provider-part-9-un-typed.aspx"&gt;Part 9 - Untyped&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;possible future installments&amp;hellip; &lt;br /&gt;&lt;br /&gt;Part 10 &amp;ndash; ETags&lt;br /&gt;Part 11 &amp;ndash; Friendly Feeds&lt;br /&gt;Part&amp;nbsp;12 &amp;ndash; Streaming &lt;br /&gt;Part&amp;nbsp;13 &amp;ndash; Advanced Paging &lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9945444" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/alexj/archive/tags/LINQ+to+SQL/">LINQ to SQL</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Entity+Framework/">Entity Framework</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Astoria/">Astoria</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Data+Services/">Data Services</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/DSP/">DSP</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Reflection+Provider/">Reflection Provider</category></item><item><title>Creating a Data Service Provider – Part 2 – IServiceProvider &amp; DataSources</title><link>http://blogs.msdn.com/b/alexj/archive/2010/01/07/creating-a-data-service-provider-part-2-iserviceprovider-datasources.aspx</link><pubDate>Thu, 07 Jan 2010 21:03:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9945396</guid><dc:creator>Alex D James</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/alexj/rsscomments.aspx?WeblogPostID=9945396</wfw:commentRss><comments>http://blogs.msdn.com/b/alexj/archive/2010/01/07/creating-a-data-service-provider-part-2-iserviceprovider-datasources.aspx#comments</comments><description>&lt;P&gt;To create a read-only Data Service Provider (or DSP) you need to implement two Data Services interfaces: &lt;STRONG&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataservicemetadataprovider(VS.100).aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataservicemetadataprovider(VS.100).aspx"&gt;IDataServiceMetadataProvider&lt;/A&gt;&lt;/STRONG&gt; to provide the metadata and &lt;STRONG&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataservicequeryprovider(VS.100).aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataservicequeryprovider(VS.100).aspx"&gt;IDataServiceQueryProvider&lt;/A&gt;&amp;nbsp;&lt;/STRONG&gt;to handle the queries.&lt;/P&gt;
&lt;P&gt;But first Data Services needs a way to find your implementations.&lt;/P&gt;
&lt;H3&gt;IServiceProvider&lt;/H3&gt;
&lt;P&gt;Data Services locates these interfaces using the &lt;A href="http://msdn.microsoft.com/en-us/library/system.iserviceprovider.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.iserviceprovider.aspx"&gt;&lt;STRONG&gt;IServiceProvider&lt;/STRONG&gt;&lt;/A&gt; interface.&amp;nbsp; &lt;BR&gt;&lt;BR&gt;Probably the best way to hook into this is to create your own class that derives from DataService&amp;lt;T&amp;gt;, and implement the IServiceProvider interface so Astoria can use that to locate your DSP interfaces:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;public class DSPDataService&amp;lt;T&amp;gt;: DataService&amp;lt;T&amp;gt;, IServiceProvider &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp; public object GetService(Type serviceType) &lt;BR&gt;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (serviceType == typeof(IDataServiceMetadataProvider)) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return … &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else if (serviceType == typeof(IDataServiceQueryProvider)) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return … &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return null; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Of course how this method actually works depends a lot upon your implementation. Which we will come back to later.&lt;/P&gt;
&lt;P&gt;But this is the starting point, and then you, or your customer, can add a Data Service to your web application or &lt;A href="http://blogs.msdn.com/alexj/archive/2009/12/11/tip-48-how-to-host-a-data-service-in-wcf.aspx" mce_href="http://blogs.msdn.com/alexj/archive/2009/12/11/tip-48-how-to-host-a-data-service-in-wcf.aspx"&gt;WCF app&lt;/A&gt;, and simply change it to derive from your class rather than the standard DataService&amp;lt;&amp;gt; like this:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;public class DemoDSPDataService : DSPDataService&amp;lt;DSPContext&amp;gt; &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp; // This method is called only once to initialize &lt;BR&gt;&amp;nbsp;&amp;nbsp; // service-wide policies. &lt;BR&gt;&amp;nbsp;&amp;nbsp; public static void InitializeService( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DataServiceConfiguration config &lt;BR&gt;&amp;nbsp;&amp;nbsp; ) &lt;BR&gt;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // TODO: replace this sample configuration with &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // real configuration &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; config.SetEntitySetAccessRule("*", EntitySetRights.AllRead); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; config.DataServiceBehavior.MaxProtocolVersion = &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DataServiceProtocolVersion.V2; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; config.DataServiceBehavior.AcceptProjectionRequests = true; &lt;BR&gt;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Here we've hooked the Data Service up to our custom DSP. &lt;BR&gt;&lt;BR&gt;Great.&lt;/P&gt;
&lt;P&gt;Of course we’ve got some work to do to actually make it work.&lt;/P&gt;
&lt;P&gt;But before we go any further lets cover data sources....&lt;/P&gt;
&lt;H3&gt;Where does the data actually come from?&lt;/H3&gt;
&lt;P&gt;If you look closely at this code:&lt;/P&gt;&lt;FONT face="Courier New"&gt;public class DemoDSPDataService : DSPDataService&amp;lt;DSPContext&amp;gt; &lt;BR&gt;{ &lt;BR&gt;&lt;/FONT&gt;
&lt;P&gt;You might wonder what DSPContext is exactly. &lt;/P&gt;
&lt;P&gt;Well it is the thing that actually represents your underlying data source, so if could be called anything.&lt;/P&gt;
&lt;P&gt;For example if you wrote a custom DSP for the Entity Framework*, DSPContext would be a class derived from &lt;A href="http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext.aspx"&gt;System.Data.Objects.ObjectContext&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#808080&gt;&lt;STRONG&gt;*NOTE:&lt;/STRONG&gt; There is no reason to do this, because Data Services includes an implementation for EF in the box.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;If your DSP allows for the underlying data source to be customized in a strongly typed way like EF you should create a generic DSPDataService class as above, and add a generic constraint, limiting T to classes that derive from one of your Data Sources:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;public class DSPDataService&amp;lt;T&amp;gt;: DataService&amp;lt;T&amp;gt;, IServiceProvider &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; where T: MyDataSource&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;If however the data-source is fixed and you don’t need a strongly typed sub-class, then something like this would be all you need:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;public class DSPDataService: DataService&amp;lt;MyDataSource&amp;gt;, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IServiceProvider&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;As you can see how you write this class depends upon your capabilities.&lt;/P&gt;
&lt;H3&gt;Next time&lt;/H3&gt;
&lt;P&gt;In &lt;A href="http://blogs.msdn.com/alexj/archive/2010/01/08/creating-a-data-service-provider-part-3-metadata.aspx" mce_href="http://blogs.msdn.com/alexj/archive/2010/01/08/creating-a-data-service-provider-part-3-metadata.aspx"&gt;Part 3&lt;/A&gt; we will look at implementing IDataServiceMetadataProvider…&lt;/P&gt;
&lt;P&gt;You can find links to all the posts in the series here.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9945396" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Astoria/">Astoria</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Data+Services/">Data Services</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/DSP/">DSP</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Walkthru/">Walkthru</category></item><item><title>Creating a Data Service Provider – Part 1 - Intro</title><link>http://blogs.msdn.com/b/alexj/archive/2010/01/04/creating-a-data-service-provider-part-1-intro.aspx</link><pubDate>Mon, 04 Jan 2010 23:57:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9943655</guid><dc:creator>Alex D James</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/alexj/rsscomments.aspx?WeblogPostID=9943655</wfw:commentRss><comments>http://blogs.msdn.com/b/alexj/archive/2010/01/04/creating-a-data-service-provider-part-1-intro.aspx#comments</comments><description>&lt;P&gt;One of the the coolest things about Data Services is its provider model. &lt;/P&gt;
&lt;P&gt;Any data-source can be exposed as an &lt;A href="http://odata.org/" mce_href="http://odata.org"&gt;OData&lt;/A&gt; Data Service simply by implementing a few interfaces. SharePoint&amp;nbsp;2010 implements these interfaces to expose list data, and you can too, to expose just about anything: Facebook? Twitter? You name it.&lt;BR&gt;&lt;BR&gt;Once you've done&amp;nbsp;that you can query the data using any of the&amp;nbsp;OData clients, including&amp;nbsp;PowerPivot,&amp;nbsp;LINQ over&amp;nbsp;Data Services etc etc.&lt;BR&gt;&amp;nbsp;&lt;BR&gt;Now Data Services ships a couple of providers in the box, including one for the Entity Framework and one that works against in memory objects using reflection. &lt;BR&gt;&lt;BR&gt;In this series of posts I will walk through creating a Custom Data Service Provider (DSP) slowly layering in more and more capabilities.&lt;/P&gt;
&lt;H3&gt;DSP Interfaces&lt;/H3&gt;
&lt;P&gt;There are 5 new interfaces:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataservicemetadataprovider(VS.100).aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataservicemetadataprovider(VS.100).aspx"&gt;IDataServiceMetadataProvider&lt;/A&gt;&lt;/STRONG&gt;:&amp;nbsp; &lt;BR&gt;Astoria uses this interface to reason about available ResourceTypes, Properties, Keys, NavigationProperties and ResourceSets. &lt;BR&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataservicequeryprovider(VS.100).aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataservicequeryprovider(VS.100).aspx"&gt;IDataServiceQueryProvider&lt;/A&gt;&lt;/STRONG&gt;: &lt;BR&gt;Astoria converts all GET requests into calls against this interface. &lt;BR&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataserviceupdateprovider(VS.100).aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataserviceupdateprovider(VS.100).aspx"&gt;IDataServiceUpdateProvider&lt;/A&gt;: &lt;BR&gt;&lt;/STRONG&gt;If your Data Source is Read/Write, you need to implement this interface because Astoria uses it for all PUT, POST and DELETE requests. &lt;BR&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataservicepagingprovider(VS.100).aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataservicepagingprovider(VS.100).aspx"&gt;IDataServicePagingProvider&lt;/A&gt;:&lt;/STRONG&gt; &lt;BR&gt;If you want to gain 'fine grained control' over&amp;nbsp;&lt;A href="http://blogs.msdn.com/astoriateam/archive/2009/03/19/ado-net-data-services-v1-5-ctp1-server-driven-paging.aspx" mce_href="http://blogs.msdn.com/astoriateam/archive/2009/03/19/ado-net-data-services-v1-5-ctp1-server-driven-paging.aspx"&gt;Server Driven&amp;nbsp;Paging&lt;/A&gt; you need to implement this interface. &lt;BR&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataservicestreamprovider(VS.100).aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataservicestreamprovider(VS.100).aspx"&gt;IDataServiceStreamProvider&lt;/A&gt;&lt;/STRONG&gt;: &lt;BR&gt;If you want to support Media Link Entries you need to need to implement this interface because Astoria uses it to manipulate the underlying stream.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;If you simply want a read-only service you only need to implement &lt;STRONG&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataservicemetadataprovider(VS.100).aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataservicemetadataprovider(VS.100).aspx"&gt;IDataServiceMetadataProvider&lt;/A&gt;&lt;/STRONG&gt; and &lt;A href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataservicequeryprovider(VS.100).aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.data.services.providers.idataservicequeryprovider(VS.100).aspx"&gt;&lt;STRONG&gt;IDataServiceQueryProvider&lt;/STRONG&gt;&lt;/A&gt;. &lt;/P&gt;
&lt;H3&gt;Next time&lt;/H3&gt;
&lt;P&gt;In&amp;nbsp;&lt;A href="http://blogs.msdn.com/alexj/archive/2010/01/07/creating-a-data-service-provider-part-2-iserviceprovider-datasources.aspx" mce_href="http://blogs.msdn.com/alexj/archive/2010/01/07/creating-a-data-service-provider-part-2-iserviceprovider-datasources.aspx"&gt;Part 2&lt;/A&gt;&amp;nbsp;we'll see how Data Services learns about your custom DSP and gets hold of your implementation of these interfaces...&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9943655" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Astoria/">Astoria</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Data+Services/">Data Services</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/DSP/">DSP</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Walkthru/">Walkthru</category></item><item><title>Tip 49 – How to find your Data Service bug</title><link>http://blogs.msdn.com/b/alexj/archive/2009/12/12/tip-49-how-to-find-your-data-service-bug.aspx</link><pubDate>Sat, 12 Dec 2009 01:41:49 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9935980</guid><dc:creator>Alex D James</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/alexj/rsscomments.aspx?WeblogPostID=9935980</wfw:commentRss><comments>http://blogs.msdn.com/b/alexj/archive/2009/12/12/tip-49-how-to-find-your-data-service-bug.aspx#comments</comments><description>&lt;p&gt;I’ve been playing around with creating a custom Astoria &lt;a href="http://msdn.microsoft.com/en-us/library/system.data.services.providers(VS.100).aspx"&gt;Data Service Provider&lt;/a&gt;, aka DSP, for a while now.&lt;/p&gt;  &lt;p&gt;So far I’d managed to get my metadata all setup, so browsing to &lt;strong&gt;$metadata&lt;/strong&gt; works great. I’d got a few simple queries work.&lt;/p&gt;  &lt;p&gt;Basically everything was going fine. &lt;/p&gt;  &lt;p&gt;At least until I tried this URL:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/Tip49HowtofindyourDataServicebug_F414/Bug_1.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Bug" border="0" alt="Bug" src="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/Tip49HowtofindyourDataServicebug_F414/Bug_thumb_1.png" width="435" height="308" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;I wasn’t sure what was going on exactly, and I couldn’t get any help from &lt;a href="http://www.fiddler2.com/fiddler2/"&gt;Fiddler&lt;/a&gt;, because it was having problems with the built-in VS web server.&lt;/p&gt;  &lt;p&gt;And because my DSP was by design loosely typed, if I needed to spot the difference between this (bad):&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/Tip49HowtofindyourDataServicebug_F414/BuggyCode.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="BuggyCode" border="0" alt="BuggyCode" src="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/Tip49HowtofindyourDataServicebug_F414/BuggyCode_thumb.png" width="624" height="279" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;And this (good):&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/Tip49HowtofindyourDataServicebug_F414/GoodCode.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="GoodCode" border="0" alt="GoodCode" src="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/Tip49HowtofindyourDataServicebug_F414/GoodCode_thumb.png" width="625" height="279" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Can you see the problem?&lt;/p&gt;  &lt;p&gt;If you can &lt;a href="http://www.urbandictionary.com/define.php?term=good%20on%20ya&amp;amp;defid=560745"&gt;good on ya&lt;/a&gt;, you’ve got sharper eyes than me…&lt;/p&gt;  &lt;p&gt;Turns out that you don’t need sharp eyes, you just need to know about &lt;strong&gt;HandleException&lt;/strong&gt; on &lt;strong&gt;DataService&amp;lt;&amp;gt;&lt;/strong&gt; which you can override something like this:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/Tip49HowtofindyourDataServicebug_F414/image_2.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/Tip49HowtofindyourDataServicebug_F414/image_thumb.png" width="699" height="354" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Once I did this it was easy to spot that one of my dictionaries had an entry keyed on &lt;strong&gt;ID&lt;/strong&gt; rather than &lt;strong&gt;Id&lt;/strong&gt;. &lt;/p&gt;  &lt;p&gt;After making the fix my query worked just great:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/Tip49HowtofindyourDataServicebug_F414/Working.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Working" border="0" alt="Working" src="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/Tip49HowtofindyourDataServicebug_F414/Working_thumb.png" width="412" height="548" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Knowing about &lt;strong&gt;HandleException&lt;/strong&gt; is absolutely vital when developing an DSP, but it is more generally useful too, for things like auditing, error logging, you name it.&lt;/p&gt;  &lt;p&gt;Oh and did you notice that my DSP exposes data from a list of dictionaries?&lt;/p&gt;  &lt;p&gt;That is a story for another day ;)&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9935980" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Tips/">Tips</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Astoria/">Astoria</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Data+Services/">Data Services</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/DSP/">DSP</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Debugging/">Debugging</category></item><item><title>Tip 48 – How to host a Data Service in WCF</title><link>http://blogs.msdn.com/b/alexj/archive/2009/12/11/tip-48-how-to-host-a-data-service-in-wcf.aspx</link><pubDate>Fri, 11 Dec 2009 06:17:40 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9935534</guid><dc:creator>Alex D James</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/alexj/rsscomments.aspx?WeblogPostID=9935534</wfw:commentRss><comments>http://blogs.msdn.com/b/alexj/archive/2009/12/11/tip-48-how-to-host-a-data-service-in-wcf.aspx#comments</comments><description>&lt;p&gt;Every wonder if you can host an Astoria Data Service in WCF? &lt;/p&gt;  &lt;p&gt;Well turns out the answer is yes, in fact once you’ve got your references set up etc it is pretty easy.&lt;/p&gt;  &lt;h3&gt;Step 1 – Setting up your project&lt;/h3&gt;  &lt;p&gt;Here is what my working project looks like:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/Tip48HowtohostaDataServiceinWCF_1397C/Project.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Project" border="0" alt="Project" src="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/Tip48HowtohostaDataServiceinWCF_1397C/Project_thumb.jpg" width="316" height="402" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;In this example I am using VS 2010 beta 2, but this should work with VS 2008 SP1 too.&lt;/p&gt;  &lt;p&gt;As you can see I have a Console app with an EF Entity Data Model called ProductsContext and a Data Service called ProductsCatalog.svc that exposes the ProductsContext.&lt;/p&gt;  &lt;p&gt;Actually getting my ProductsCatalog.svc into my Console App was a little tricky – If you try Add New Item you won’t find Add Data Service because that dialog is project type sensitive, so it filters out options it considered unlikely in a Console App – I got around this by creating the Data Service in temporary Web Application project and copying it into my Console App project.&lt;/p&gt;  &lt;p&gt;Then you need references to the appropriate assemblies &lt;strong&gt;System.Data.Entity&lt;/strong&gt; (EF), &lt;strong&gt;System.Data.Services&lt;/strong&gt; &amp;amp; &lt;strong&gt;System.Data.Services.Client&lt;/strong&gt; (Astoria) and &lt;strong&gt;System.ServiceModel&lt;/strong&gt; &amp;amp; &lt;strong&gt;System.ServiceModel.Web&lt;/strong&gt; (WCF).&lt;/p&gt;  &lt;p&gt;Now we have our project all ready to go, the next step is…&lt;/p&gt;  &lt;h3&gt;Step 2 – Exposing your Data Service&lt;/h3&gt;  &lt;p&gt;And now, courtesy of &lt;a href="http://blogs.msdn.com/phaniraj/"&gt;Phani&lt;/a&gt;, this code is all you need to expose the Data Service:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;string uriBaseAddress = &amp;quot;&lt;/font&gt;&lt;a href="http://localhost:998&amp;quot;;"&gt;&lt;font face="Courier New"&gt;http://localhost:998&amp;quot;;&lt;/font&gt;&lt;/a&gt;    &lt;br /&gt;&lt;font face="Courier New"&gt;Uri[] uriArray = { new Uri(uriBaseAddress) };     &lt;br /&gt;Type serviceType = typeof(ProductsCatalog); &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;using(WebServiceHost host = new WebServiceHost(serviceType, uriArray))     &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; try      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; host.Open();      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Console.ReadKey();      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; catch (Exception ex)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Console.WriteLine(&amp;quot;An exception occurred:&amp;quot;);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Console.WriteLine(ex.ToString());      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; host.Abort();      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Console.WriteLine(&amp;quot;Aborting&amp;quot;);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Console.ReadKey();      &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;As you can see we simply create a WebServiceHost for our Data Service class with the URL you want the service to be bound to. Simple. &lt;/p&gt;  &lt;p&gt;And now you should be able to do things like this:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/Tip48HowtohostaDataServiceinWCF_1397C/View_1.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="View" border="0" alt="View" src="http://blogs.msdn.com/blogfiles/alexj/WindowsLiveWriter/Tip48HowtohostaDataServiceinWCF_1397C/View_thumb_1.jpg" width="244" height="154" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;All exposed through your own little console app.&lt;/p&gt;  &lt;p&gt;Nifty huh?&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9935534" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Astoria/">Astoria</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/Data+Services/">Data Services</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/EF+3-5/">EF 3.5</category><category domain="http://blogs.msdn.com/b/alexj/archive/tags/WCF/">WCF</category></item></channel></rss>
