<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://community.bartdesmet.net/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>LINQ to SharePoint : Internals</title><link>http://community.bartdesmet.net/blogs/linqtosharepoint/archive/tags/Internals/default.aspx</link><description>Tags: Internals</description><dc:language>en</dc:language><generator>CommunityServer 2007 (Build: 20423.869)</generator><item><title>Lookup fields inside out</title><link>http://community.bartdesmet.net/blogs/linqtosharepoint/archive/2007/07/10/lookup-fields-inside-out.aspx</link><pubDate>Tue, 10 Jul 2007 23:14:28 GMT</pubDate><guid isPermaLink="false">863c5522-913f-4a64-ac0a-bd5f05abad0f:12598</guid><dc:creator>bart</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.bartdesmet.net/blogs/linqtosharepoint/rsscomments.aspx?PostID=12598</wfw:commentRss><comments>http://community.bartdesmet.net/blogs/linqtosharepoint/archive/2007/07/10/lookup-fields-inside-out.aspx#comments</comments><description>&lt;h2&gt;&lt;strong&gt;&lt;font color="#000080"&gt;Introduction&lt;/font&gt;&lt;/strong&gt;&lt;/h2&gt; &lt;p&gt;Lookup fields are one of the most powerful list-related features of SharePoint, together with their big brothers, the LookupMulti fields. First of all, let&amp;#39;s introduce these field types briefly. In the screenshot below you can see a Northwind Products list in SharePoint with at the right-hand side two Lookup fields: Category en Supplier. These two fields refer to items in another list, in this case Categories and Suppliers:&lt;/p&gt; &lt;p&gt;&lt;a href="http://community.bartdesmet.net/blogs/linqtosharepoint/WindowsLiveWriter/Lookupfieldsinsideout_13614/image_1.png"&gt;&lt;img style="border-right:0px;border-top:0px;border-left:0px;border-bottom:0px;" height="155" alt="image" src="http://community.bartdesmet.net/blogs/linqtosharepoint/WindowsLiveWriter/Lookupfieldsinsideout_13614/image_thumb_1.png" width="240" border="0" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;The definition of such a field is shown below:&lt;/p&gt; &lt;p&gt;&lt;a href="http://community.bartdesmet.net/blogs/linqtosharepoint/WindowsLiveWriter/Lookupfieldsinsideout_13614/image_2.png"&gt;&lt;img style="border-right:0px;border-top:0px;border-left:0px;border-bottom:0px;" height="189" alt="image" src="http://community.bartdesmet.net/blogs/linqtosharepoint/WindowsLiveWriter/Lookupfieldsinsideout_13614/image_thumb_2.png" width="240" border="0" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Using &amp;#39;Allow multiple values&amp;#39;, you can turn the column into a LookupMulti list, referring to multiple items instead of just one.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h2&gt;&lt;strong&gt;&lt;font color="#000080"&gt;How to map? SPML is your friend!&lt;/font&gt;&lt;/strong&gt;&lt;/h2&gt; &lt;p&gt;So far so good. But how can we use these fields in LINQ to SharePoint? Of course it all starts by creating the entity types. To do this, we can either use the SpMetal command line tool, or (starting with the upcoming 0.2.1 interim release) the SPML mapping language. It&amp;#39;s sufficient to map just the Products list, the entity generator will automatically figure out all of the lists that are referred to in the list&amp;#39;s definition recursively, either using Lookup or LookupMulti fields. The entity generator is smart enough to eliminate cycles in such a list cross-reference graph and export all of the entity types you need. In this case, I&amp;#39;ll just export the Products list with the following SPML definition:&lt;/p&gt; &lt;p&gt;&amp;lt;&lt;font color="#800000"&gt;SharePointDataContext&lt;/font&gt; &lt;font color="#ff0000"&gt;Name&lt;/font&gt;=&amp;quot;&lt;font color="#0000ff"&gt;Demo&lt;/font&gt;&amp;quot; &lt;font color="#ff0000"&gt;Url&lt;/font&gt;=&amp;quot;&lt;u&gt;&lt;font color="#0000ff"&gt;http://wss3demo&lt;/font&gt;&lt;/u&gt;&amp;quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;font color="#800000"&gt;Lists&lt;/font&gt;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;font color="#800000"&gt;List&lt;/font&gt; &lt;font color="#ff0000"&gt;Name&lt;/font&gt;=&amp;quot;&lt;font color="#0000ff"&gt;Products&lt;/font&gt;&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/&lt;font color="#800000"&gt;Lists&lt;/font&gt;&amp;gt;&lt;br /&gt;&amp;lt;/&lt;font color="#800000"&gt;SharePointDataContext&lt;/font&gt; &amp;gt; &lt;p&gt;As with all SPML files you still need to set the Custom Tool manually:&lt;/p&gt; &lt;p&gt;&lt;a href="http://community.bartdesmet.net/blogs/linqtosharepoint/WindowsLiveWriter/Lookupfieldsinsideout_13614/image_3.png"&gt;&lt;img style="border-right:0px;border-top:0px;border-left:0px;border-bottom:0px;" height="240" alt="image" src="http://community.bartdesmet.net/blogs/linqtosharepoint/WindowsLiveWriter/Lookupfieldsinsideout_13614/image_thumb_3.png" width="155" border="0" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;This will change in the future when we have a Project Item for SPML files, as well as a designer down the road. Now, when we run the entity generator as follows:&lt;/p&gt; &lt;p&gt;&lt;a href="http://community.bartdesmet.net/blogs/linqtosharepoint/WindowsLiveWriter/Lookupfieldsinsideout_13614/image_4.png"&gt;&lt;img style="border-right:0px;border-top:0px;border-left:0px;border-bottom:0px;" height="240" alt="image" src="http://community.bartdesmet.net/blogs/linqtosharepoint/WindowsLiveWriter/Lookupfieldsinsideout_13614/image_thumb_4.png" width="155" border="0" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;it will generate the entity types for the Products lists as well as the Suppliers and Categories lists that are referred to:&lt;/p&gt; &lt;p&gt;&lt;a href="http://community.bartdesmet.net/blogs/linqtosharepoint/WindowsLiveWriter/Lookupfieldsinsideout_13614/image_5.png"&gt;&lt;img style="border-right:0px;border-top:0px;border-left:0px;border-bottom:0px;" height="150" alt="image" src="http://community.bartdesmet.net/blogs/linqtosharepoint/WindowsLiveWriter/Lookupfieldsinsideout_13614/image_thumb_5.png" width="240" border="0" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h2&gt;&lt;strong&gt;&lt;font color="#000080"&gt;Introducing deferred loading&lt;/font&gt;&lt;/strong&gt;&lt;/h2&gt; &lt;p&gt;Time to write some simple&amp;nbsp;query now:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font color="#008080"&gt;DemoSharePointDataContext&lt;/font&gt; ctx = &lt;font color="#0000ff"&gt;new&lt;/font&gt; &lt;font color="#008080"&gt;DemoSharePointDataContext&lt;/font&gt;(&lt;font color="#0000ff"&gt;new &lt;/font&gt;Uri(&lt;font color="#800000"&gt;&amp;quot;http://wss3demo&amp;quot;&lt;/font&gt;));&lt;br /&gt;ctx.Log = &lt;font color="#008080"&gt;Console&lt;/font&gt;.Out;&lt;br /&gt;&lt;font color="#0000ff"&gt;var &lt;/font&gt;res = (&lt;font color="#0000ff"&gt;from &lt;/font&gt;p in ctx.Products &lt;font color="#0000ff"&gt;where &lt;/font&gt;p.ProductName == &lt;font color="#800000"&gt;&amp;quot;Chai&amp;quot;&lt;/font&gt; &lt;font color="#0000ff"&gt;select &lt;/font&gt;p).AsEnumerable().Single();&lt;br /&gt;&lt;font color="#008080"&gt;Console&lt;/font&gt;.WriteLine(&lt;font color="#800000"&gt;&amp;quot;{0} costs {1} per {2}&amp;quot;&lt;/font&gt;, res.ProductName, res.UnitPrice, res.QuantityPerUnit);&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;On the fourth line you can see a very simple query that just selects on the product&amp;#39;s name. The Single query operator isn&amp;#39;t implemented in LINQ to SharePoint currently, so we insert an AsEnumerable() call to perform the subsequent Single call via LINQ to Objects. After all, this is how the execution looks like:&lt;/p&gt; &lt;p&gt;&lt;a href="http://community.bartdesmet.net/blogs/linqtosharepoint/WindowsLiveWriter/Lookupfieldsinsideout_13614/image_6.png"&gt;&lt;img style="border-right:0px;border-top:0px;border-left:0px;border-bottom:0px;" height="136" alt="image" src="http://community.bartdesmet.net/blogs/linqtosharepoint/WindowsLiveWriter/Lookupfieldsinsideout_13614/image_thumb_6.png" width="240" border="0" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;However, what about accessing the Category property of the entity object? To illustrate this, add the following line of code:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font color="#008080"&gt;Console&lt;/font&gt;.WriteLine(&lt;font color="#800000"&gt;&amp;quot;Category of {0} is {1}&amp;quot;&lt;/font&gt;, res.ProductName, &lt;em&gt;res.Category&lt;/em&gt;.CategoryName);&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;In here, we refer to res.Category which is obtained using &lt;strong&gt;deferred loading&lt;/strong&gt;, meaning that we only get the Category data back when the user asks for it:&lt;/p&gt; &lt;p&gt;&lt;a href="http://community.bartdesmet.net/blogs/linqtosharepoint/WindowsLiveWriter/Lookupfieldsinsideout_13614/image_8.png"&gt;&lt;img style="border-right:0px;border-top:0px;border-left:0px;border-bottom:0px;" height="119" alt="image" src="http://community.bartdesmet.net/blogs/linqtosharepoint/WindowsLiveWriter/Lookupfieldsinsideout_13614/image_thumb_8.png" width="240" border="0" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;If you want to get the data right away when executing the query, you could use it in the projection portion of the query:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font color="#0000ff"&gt;var &lt;/font&gt;res = (&lt;font color="#0000ff"&gt;from &lt;/font&gt;p in ctx.Products &lt;font color="#0000ff"&gt;where &lt;/font&gt;p.ProductName == &lt;font color="#800000"&gt;&amp;quot;Chai&amp;quot;&lt;/font&gt; &lt;font color="#0000ff"&gt;select new &lt;/font&gt;{&amp;nbsp;p.ProductName, p.UnitPrice, p.QuantityPerUnit, p.Category&amp;nbsp;}).AsEnumerable().Single();&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;a href="http://community.bartdesmet.net/blogs/linqtosharepoint/WindowsLiveWriter/Lookupfieldsinsideout_13614/image_10.png"&gt;&lt;img style="border-right:0px;border-top:0px;border-left:0px;border-bottom:0px;" height="179" alt="image" src="http://community.bartdesmet.net/blogs/linqtosharepoint/WindowsLiveWriter/Lookupfieldsinsideout_13614/image_thumb_10.png" width="240" border="0" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Observe the place where the query gets executed, it&amp;#39;s now part of the Products list query operation. You might wonder why we can&amp;#39;t do something SQL&amp;#39;ish to join between lists and get data back that way. The answer is pretty simple: in CAML you&amp;#39;re restricted to querying one list at a time, so we can&amp;#39;t do any better.&lt;/p&gt; &lt;p&gt;Notice the way the &amp;quot;subquery&amp;quot; is composed, as a CAML query using the ID field. This is because we&amp;#39;re able to get identity information of child lists used in Lookup fields&amp;nbsp;(i.e. Category and Supplier) when querying the parent list (in this case Products). Internally, LINQ to SharePoint keeps this data in&amp;nbsp;a so-called LazyLoadingThunk object that&amp;#39;s stored in the entity object&amp;#39;s fields dictionary. When the data for such a field is retrieved using an entity property (which calls into the GetValue method of the base SharePointListEntity class, see fragment below), the LazyLoadingThunk grabs the ID and sends a request to the data context object to go and retrieve that object using a &amp;quot;GetEntityById&amp;quot; call:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;[&lt;font color="#0000ff"&gt;global&lt;/font&gt;::BdsSoft.SharePoint.Linq.&lt;font color="#008080"&gt;FieldAttribute&lt;/font&gt;(&lt;font color="#800000"&gt;&amp;quot;Category&amp;quot;&lt;/font&gt;, &lt;font color="#0000ff"&gt;global&lt;/font&gt;::BdsSoft.SharePoint.Linq.&lt;font color="#008080"&gt;FieldType&lt;/font&gt;.Lookup, Id=&lt;font color="#800000"&gt;&amp;quot;...&amp;quot;&lt;/font&gt;, LookupField=&lt;font color="#800000"&gt;&amp;quot;CategoryName&amp;quot;&lt;/font&gt;)]&lt;br /&gt;&lt;font color="#0000ff"&gt;public&lt;/font&gt; &lt;font color="#008080"&gt;Categories &lt;/font&gt;Category {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;get&lt;/font&gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;return &lt;/font&gt;((&lt;font color="#008080"&gt;Categories&lt;/font&gt;)(&lt;font color="#0000ff"&gt;base&lt;/font&gt;.&lt;u&gt;GetValue&lt;/u&gt;(&lt;font color="#800000"&gt;&amp;quot;Category&amp;quot;&lt;/font&gt;)));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;set &lt;/font&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;base&lt;/font&gt;.SetValue(&lt;font color="#800000"&gt;&amp;quot;Category&amp;quot;&lt;/font&gt;, &lt;font color="#0000ff"&gt;value&lt;/font&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;LookupMulti fields are treated in a similar way with an entity property that&amp;#39;s a collection type instead (in the current release we use IList&amp;lt;T&amp;gt; as the property type for a LookupMulti field in an entity type, where T stands for another SharePointListEntity subclass). E.g. if the Products list would have a LookupMulti Categories property instead, you&amp;#39;d get an entity definition with a property similar to the following:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;[&lt;font color="#0000ff"&gt;global&lt;/font&gt;::BdsSoft.SharePoint.Linq.&lt;font color="#008080"&gt;FieldAttribute&lt;/font&gt;(&lt;font color="#800000"&gt;&amp;quot;Categories&amp;quot;&lt;/font&gt;, &lt;font color="#0000ff"&gt;global&lt;/font&gt;::BdsSoft.SharePoint.Linq.&lt;font color="#008080"&gt;FieldType&lt;/font&gt;.LookupMulti, Id=&lt;font color="#800000"&gt;&amp;quot;...&amp;quot;&lt;/font&gt;, LookupField=&lt;font color="#800000"&gt;&amp;quot;CategoryName&amp;quot;&lt;/font&gt;)]&lt;br /&gt;&lt;font color="#0000ff"&gt;public&lt;/font&gt; &lt;font color="#008080"&gt;IList&lt;/font&gt;&amp;lt;&lt;font color="#008080"&gt;Categories&lt;/font&gt;&amp;gt; Categories {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;get&lt;/font&gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;return &lt;/font&gt;((&lt;font color="#008080"&gt;IList&lt;/font&gt;&amp;lt;&lt;font color="#008080"&gt;Categories&lt;/font&gt;&amp;gt;)(&lt;font color="#0000ff"&gt;base&lt;/font&gt;.GetValue(&lt;font color="#800000"&gt;&amp;quot;Categories&amp;quot;&lt;/font&gt;)));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;set &lt;/font&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;base&lt;/font&gt;.SetValue(&lt;font color="#800000"&gt;&amp;quot;Categories&amp;quot;&lt;/font&gt;, &lt;font color="#0000ff"&gt;value&lt;/font&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;u&gt;Note:&lt;/u&gt; If you don&amp;#39;t want to write a projection that calls the Category property (or another Lookup or LookupMulti field) manually in order to retrieve the data right away (which also returns non-entity types which won&amp;#39;t support updating), we&amp;#39;ll provide some other feature modeled after LINQ to SQL &amp;quot;&lt;strong&gt;data shapes&lt;/strong&gt;&amp;quot; in a future release. Such a data shape instructs the data provider to retrieve some fields (in our case typically Lookup or LookupMulti fields) right away when writing a query, even when such&amp;nbsp;a query doesn&amp;#39;t include that field directly (e.g. in a projection). I&amp;#39;ll blog about this feature once we get there in the release cycle.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h2&gt;&lt;strong&gt;&lt;font color="#000080"&gt;Using subqueries&lt;/font&gt;&lt;/strong&gt;&lt;/h2&gt; &lt;p&gt;However, there&amp;#39;s more than just deferred loading when talking about Lookup(Multi) fields. What about querying the parent list in a way like this:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font color="#0000ff"&gt;var &lt;/font&gt;res = &lt;font color="#0000ff"&gt;from &lt;/font&gt;p &lt;font color="#0000ff"&gt;in &lt;/font&gt;ctx.Products &lt;font color="#0000ff"&gt;where &lt;/font&gt;p.Category.CategoryName.StartsWith(&lt;font color="#800000"&gt;&amp;quot;Con&amp;quot;&lt;/font&gt;) &lt;font color="#0000ff"&gt;select &lt;/font&gt;p;&lt;br /&gt;&lt;font color="#0000ff"&gt;foreach&lt;/font&gt; (&lt;font color="#0000ff"&gt;var &lt;/font&gt;p &lt;font color="#0000ff"&gt;in &lt;/font&gt;res)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#008080"&gt;Console&lt;/font&gt;.WriteLine(&lt;font color="#800000"&gt;&amp;quot;{0} in category {1} costs {2} per unit&amp;quot;&lt;/font&gt;, p.ProductName, p.Category.CategoryName, p.UnitPrice);&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Since we can&amp;#39;t query for multiple lists using just one CAML query, e.g. by doing joins, we have to play quite some tricks to get this to work. When we set a breakpoint on the foreach loop, we can take a look at the &lt;em&gt;res&lt;/em&gt; object at runtime:&lt;/p&gt; &lt;p&gt;&lt;a href="http://community.bartdesmet.net/blogs/linqtosharepoint/WindowsLiveWriter/Lookupfieldsinsideout_13614/image_12.png"&gt;&lt;img style="border-right:0px;border-top:0px;border-left:0px;border-bottom:0px;" height="192" alt="image" src="http://community.bartdesmet.net/blogs/linqtosharepoint/WindowsLiveWriter/Lookupfieldsinsideout_13614/image_thumb_12.png" width="640" border="0" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;This is the result as shown in the debugger visualizer:&lt;/p&gt; &lt;p&gt;&lt;a href="http://community.bartdesmet.net/blogs/linqtosharepoint/WindowsLiveWriter/Lookupfieldsinsideout_13614/image_13.png"&gt;&lt;img style="border-right:0px;border-top:0px;border-left:0px;border-bottom:0px;" height="161" alt="image" src="http://community.bartdesmet.net/blogs/linqtosharepoint/WindowsLiveWriter/Lookupfieldsinsideout_13614/image_thumb_13.png" width="240" border="0" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Observe the portion I&amp;#39;ve indicated in the red rectangle. It isn&amp;#39;t valid CAML, it&amp;#39;s a so-called &lt;strong&gt;patch&lt;/strong&gt;. Such a patch gets generated by the front-end portion of the parser whenever it observes a &amp;quot;traversal&amp;quot; (such as &lt;u&gt;p.Category&lt;/u&gt;.CategoryName.StartsWith(&lt;font color="#800000"&gt;&amp;quot;Con&amp;quot;&lt;/font&gt;))&amp;nbsp;of a Lookup field in the query predicate (where clause). When the query has to be sent to the server in order to retrieve results, the contents of each patch is wrapped in a separate query that&amp;#39;s executed against the entity type specified by the Patch element&amp;#39;s Field attribute. Based on the results of this &lt;strong&gt;subquery&lt;/strong&gt;, the Patch element is replaced by a tree of &amp;lt;Or&amp;gt; tags in order to select only those list items from the parent list that reference a category that&amp;#39;s matching with the patch&amp;#39;s query. This looks pretty much like a foreign key lookup in relational databases.&lt;/p&gt; &lt;p&gt;&lt;u&gt;Note:&lt;/u&gt; In releases prior to the 0.2.1 interim release, the situation was much more complex (cf. FieldAttribute::IsUnique and EnforeLookupFieldUniqueness)&amp;nbsp;because of the lacking documentation of how to do a &amp;quot;lookup field query &lt;u&gt;by value&lt;/u&gt;&amp;quot;. There&amp;#39;s however an undocumented &lt;strong&gt;LookupId&lt;/strong&gt; attribute on the CAML FieldRef element that allows to do exactly this.&lt;/p&gt; &lt;p&gt;For our sample query, this is the resulting execution plan:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;First, the Category patch is executed. This subquery retrieves the ID field values for all of the categories that start with Con.&lt;br /&gt;&lt;br /&gt;&amp;lt;Query&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;Where&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;BeginsWith&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;FieldRef Name=&amp;quot;CategoryName&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Value Type=&amp;quot;Text&amp;quot;&amp;gt;Con&amp;lt;/Value&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/BeginsWith&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;/Where&amp;gt;&lt;br /&gt;&amp;lt;/Query&amp;gt;&lt;br /&gt;&amp;lt;ViewFields&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;FieldRef Name=&amp;quot;ID&amp;quot; /&amp;gt;&lt;br /&gt;&amp;lt;/ViewFields&amp;gt;&lt;br /&gt;&lt;/li&gt; &lt;li&gt;Now, the Category patch is cut from the original pre-parsed query and replaced by a tree of &amp;lt;Or&amp;gt;-conditions chaining all matching category IDs together, like this:&lt;/li&gt; &lt;p&gt;&amp;lt;Query&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;Where&amp;gt;&lt;br /&gt;&lt;font color="#008000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Or&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Eq&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Value Type=&amp;quot;Lookup&amp;quot;&amp;gt;3&amp;lt;/Value&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;FieldRef Name=&amp;quot;Category&amp;quot; LookupId=&amp;quot;TRUE&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Eq&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Eq&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Value Type=&amp;quot;Lookup&amp;quot;&amp;gt;2&amp;lt;/Value&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;FieldRef Name=&amp;quot;Category&amp;quot; LookupId=&amp;quot;TRUE&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Eq&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Or&amp;gt;&lt;/font&gt;&lt;br /&gt;&amp;nbsp; &amp;lt;/Where&amp;gt;&lt;br /&gt;&amp;lt;/Query&amp;gt;&lt;/p&gt;&lt;/ol&gt; &lt;p&gt;As an example, let&amp;#39;s make it a little more difficult with two patches involved. Observe the following query:&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" size="2"&gt;&lt;font color="#0000ff"&gt;var&lt;/font&gt; res = &lt;font color="#0000ff"&gt;from &lt;/font&gt;p &lt;font color="#0000ff"&gt;in &lt;/font&gt;ctx.Products&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;where &lt;/font&gt;p.Category.CategoryName.StartsWith(&lt;font color="#800000"&gt;&amp;quot;Con&amp;quot;&lt;/font&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;amp;&amp;amp; (p.Supplier.Country == &lt;font color="#800000"&gt;&amp;quot;USA&amp;quot;&lt;/font&gt; &amp;amp;&amp;amp; p.Supplier.Region == &lt;font color="#800000"&gt;&amp;quot;LA&amp;quot;&lt;br /&gt;&lt;/font&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; || p.Supplier.Country == &lt;font color="#800000"&gt;&amp;quot;Canada&amp;quot;&lt;/font&gt; &amp;amp;&amp;amp; p.Supplier.Region == &lt;font color="#800000"&gt;&amp;quot;Québec&amp;quot;&lt;/font&gt;)&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 color="#0000ff"&gt;select &lt;/font&gt;p;&lt;/font&gt; &lt;p&gt;Time to see what the parser builds out of this LINQ query, so take a look at the visualizer screenshot below: &lt;p&gt;&lt;a href="http://community.bartdesmet.net/blogs/linqtosharepoint/WindowsLiveWriter/Lookupfieldsinsideout_13614/image_15.png"&gt;&lt;img style="border-right:0px;border-top:0px;border-left:0px;border-bottom:0px;" height="240" alt="image" src="http://community.bartdesmet.net/blogs/linqtosharepoint/WindowsLiveWriter/Lookupfieldsinsideout_13614/image_thumb_15.png" width="175" border="0" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Observe we have two patches this time. The parser is smart enough to coalesce adjacent lookup field traversals, in this case the whole query predicate portion for the supplier condition (USA/LA or Canada/Québec) is brought together in just one patch. This means that LINQ to SharePoint will launch two subqueries before taking on the parent query:&lt;/p&gt; &lt;p&gt;&lt;u&gt;Query corresponding with p.Category.CategoryName.StartsWith(&lt;font color="#800000"&gt;&amp;quot;Con&amp;quot;&lt;/font&gt;):&lt;/u&gt;&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&amp;lt;Query&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;Where&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;BeginsWith&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;FieldRef Name=&amp;quot;CategoryName&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Value Type=&amp;quot;Text&amp;quot;&amp;gt;Con&amp;lt;/Value&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/BeginsWith&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;/Where&amp;gt;&lt;br /&gt;&amp;lt;/Query&amp;gt;&lt;br /&gt;&amp;lt;ViewFields&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;FieldRef Name=&amp;quot;ID&amp;quot; /&amp;gt;&lt;br /&gt;&amp;lt;/ViewFields&amp;gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;u&gt;Query corresponding with (p.Supplier.Country == &lt;font color="#800000"&gt;&amp;quot;USA&amp;quot;&lt;/font&gt; &amp;amp;&amp;amp; p.Supplier.Region == &lt;font color="#800000"&gt;&amp;quot;LA&amp;quot; &lt;/font&gt;|| p.Supplier.Country == &lt;font color="#800000"&gt;&amp;quot;Canada&amp;quot;&lt;/font&gt; &amp;amp;&amp;amp; p.Supplier.Region == &lt;font color="#800000"&gt;&amp;quot;Québec&amp;quot;&lt;/font&gt;):&lt;/u&gt;&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&amp;lt;Query&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;Where&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Or&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;And&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Eq&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Value Type=&amp;quot;Text&amp;quot;&amp;gt;USA&amp;lt;/Value&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;FieldRef Name=&amp;quot;Country&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Eq&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Eq&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Value Type=&amp;quot;Text&amp;quot;&amp;gt;LA&amp;lt;/Value&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;FieldRef Name=&amp;quot;Region&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Eq&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/And&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;And&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Eq&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Value Type=&amp;quot;Text&amp;quot;&amp;gt;Canada&amp;lt;/Value&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;FieldRef Name=&amp;quot;Country&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Eq&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Eq&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Value Type=&amp;quot;Text&amp;quot;&amp;gt;Québec&amp;lt;/Value&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;FieldRef Name=&amp;quot;Region&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Eq&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/And&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Or&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;/Where&amp;gt;&lt;br /&gt;&amp;lt;/Query&amp;gt;&lt;br /&gt;&amp;lt;ViewFields&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;FieldRef Name=&amp;quot;ID&amp;quot; /&amp;gt;&lt;br /&gt;&amp;lt;/ViewFields&amp;gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Next, it will patch the parent query with all of the patch information gathered, resulting in the following: &lt;p&gt;&lt;a href="http://community.bartdesmet.net/blogs/linqtosharepoint/WindowsLiveWriter/Lookupfieldsinsideout_13614/image_16.png"&gt;&lt;img style="border-right:0px;border-top:0px;border-left:0px;border-bottom:0px;" height="222" alt="image" src="http://community.bartdesmet.net/blogs/linqtosharepoint/WindowsLiveWriter/Lookupfieldsinsideout_13614/image_thumb_16.png" width="240" border="0" /&gt;&lt;/a&gt;  &lt;p&gt;Finally this piece of CAML is ready for execution by the server to get the final results back. &lt;p&gt;As a final feature under the umbrella of Lookup field support, you can also use entity objects in the query predicate directly, like this: &lt;blockquote&gt; &lt;p&gt;&lt;font color="#0000ff"&gt;var &lt;/font&gt;cat = (&lt;font color="#0000ff"&gt;from&amp;nbsp;&lt;/font&gt;&lt;font color="#000000"&gt;c&lt;/font&gt; &lt;font color="#0000ff"&gt;in &lt;/font&gt;ctx.Categories &lt;font color="#0000ff"&gt;where &lt;/font&gt;p.CategoryName == &lt;font color="#800000"&gt;&amp;quot;Beverages&amp;quot;&lt;/font&gt; &lt;font color="#0000ff"&gt;select &lt;/font&gt;c).First();&lt;font color="#008000"&gt; //we don&amp;#39;t support the Single query operator, so use First to get the &amp;#39;singleton result&amp;#39;&lt;/font&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;var &lt;/font&gt;res = &lt;font color="#0000ff"&gt;from &lt;/font&gt;p &lt;font color="#0000ff"&gt;in &lt;/font&gt;ctx.Products &lt;font color="#0000ff"&gt;where &lt;/font&gt;p.Category == cat &lt;font color="#0000ff"&gt;select &lt;/font&gt;p;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;This will grab the primary key field value from the cat variable and use it in similar way as the samples above. &lt;p&gt;&amp;nbsp; &lt;h2&gt;&lt;strong&gt;&lt;font color="#000080"&gt;Quiz&lt;/font&gt;&lt;/strong&gt;&lt;/h2&gt; &lt;p&gt;If you think you&amp;#39;ve understood everything in this post, here&amp;#39;s a little &lt;strong&gt;quiz&lt;/strong&gt;. How many distinct queries will be sent to the server in order to execute the following LINQ query? &lt;blockquote&gt; &lt;p&gt;&lt;font color="#0000ff"&gt;var &lt;/font&gt;res = &lt;font color="#0000ff"&gt;from &lt;/font&gt;p &lt;font color="#0000ff"&gt;in &lt;/font&gt;ctx.Products &lt;font color="#0000ff"&gt;where &lt;/font&gt;p.UnitPrice &amp;lt;= 20 &amp;amp;&amp;amp; (p.Category.CategoryName == &lt;font color="#800000"&gt;&amp;quot;Beverages&amp;quot;&lt;/font&gt; || p.Category.CategoryName == &lt;font color="#800000"&gt;&amp;quot;Seafood&amp;quot;&lt;/font&gt;) &amp;amp;&amp;amp; p.Supplier.Country == &lt;font color="#800000"&gt;&amp;quot;USA&amp;quot;&lt;/font&gt; &lt;font color="#0000ff"&gt;orderby &lt;/font&gt;p.UnitPrice &lt;font color="#0000ff"&gt;descending select &lt;/font&gt;p;&lt;br /&gt;&lt;font color="#0000ff"&gt;foreach &lt;/font&gt;(&lt;font color="#0000ff"&gt;var &lt;/font&gt;p &lt;font color="#0000ff"&gt;in &lt;/font&gt;res)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;font color="#008080"&gt;Console&lt;/font&gt;.WriteLine(&lt;font color="#800000"&gt;&amp;quot;{0} in category {1} costs {2} and is supplied by {3}.&amp;quot;&lt;/font&gt;, p.ProductName, p.Category.CategoryName, p.UnitPrice, p.Supplier.CompanyName);&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;The output is shown below (&lt;u&gt;tip:&lt;/u&gt; why is this relevant?). &lt;blockquote&gt; &lt;p&gt;Boston Crab Meat in category Seafood costs 18,4 and is supplied by New England Seafood Cannery.&lt;br /&gt;Steeleye Stout in category Beverages costs 18 and is supplied by Bigfoot Breweries.&lt;br /&gt;Sasquatch Ale in category Beverages costs 14 and is supplied by Bigfoot Breweries.&lt;br /&gt;Laughing Lumberjack Lager in category Beverages costs 14 and is supplied by Bigfoot Breweries.&lt;br /&gt;Jack&amp;#39;s New England Clam Chowder in category Seafood costs 9,65 and is supplied by New England Seafood Cannery.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&amp;nbsp; &lt;h2&gt;&lt;strong&gt;&lt;font color="#000080"&gt;Conclusion&lt;/font&gt;&lt;/strong&gt;&lt;/h2&gt; &lt;p&gt;As you can see, this feature in LINQ to SharePoint frees developers from the burden of having to execute more than one CAML query in order to get the desired results back. In the upcoming 0.2.1 interim release, this feature is fully functional, ready for you to play with it. Notice however that we don&amp;#39;t support lookup field traversals deeper than one. For example, if an item from a Product list has a supplier from a Suppliers list with an address stored in an Addresses list, it won&amp;#39;t be possible to write a predicate like p.Supplier.Address.City == &amp;quot;Seattle&amp;quot; (Address is one bridge too far). This might be subject of a future release if time permits.&lt;/p&gt;&lt;img src="http://community.bartdesmet.net/aggbug.aspx?PostID=12598" width="1" height="1"&gt;</description><category domain="http://community.bartdesmet.net/blogs/linqtosharepoint/archive/tags/Internals/default.aspx">Internals</category></item><item><title>Improving the parser and more debugger visualizer fun</title><link>http://community.bartdesmet.net/blogs/linqtosharepoint/archive/2007/07/05/linq-to-sharepoint-improving-the-parser-debugger-visualizer-fun.aspx</link><pubDate>Thu, 05 Jul 2007 08:00:00 GMT</pubDate><guid isPermaLink="false">863c5522-913f-4a64-ac0a-bd5f05abad0f:12585</guid><dc:creator>bart</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.bartdesmet.net/blogs/linqtosharepoint/rsscomments.aspx?PostID=12585</wfw:commentRss><comments>http://community.bartdesmet.net/blogs/linqtosharepoint/archive/2007/07/05/linq-to-sharepoint-improving-the-parser-debugger-visualizer-fun.aspx#comments</comments><description>&lt;p&gt;Welcome back to what&amp;#39;s going to end up as &lt;em&gt;&amp;quot;LINQ to SharePoint: The Cruel Sequel&amp;quot;&lt;/em&gt; :-). The last couple of days, LINQ to SharePoint has been a full-time job and the result is getting better and better build after build. In this post, I&amp;#39;d like to highlight another feature that was planned from the start but didn&amp;#39;t make its way to the 0.2 release of last month: &lt;strong&gt;parser enhancements&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;So, what&amp;#39;s up? Simply stated, the query parser so far was a runtime parser only. When executing LINQ to SharePoint queries, the LINQ query expression tree gets parsed sooner or later, possibly throwing exceptions in case something can&amp;#39;t be translated into CAML. A typical example is the following:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;&lt;font color="#0000ff"&gt;var &lt;/font&gt;res = &lt;font color="#0000ff"&gt;from&amp;nbsp;&lt;/font&gt;u &lt;font color="#0000ff"&gt;in &lt;/font&gt;users &lt;font color="#0000ff"&gt;where &lt;/font&gt;u.FirstName.&lt;u&gt;EndsWith&lt;/u&gt;(&lt;font color="#800000"&gt;&amp;quot;t&amp;quot;&lt;/font&gt;) &lt;font color="#0000ff"&gt;select&lt;/font&gt; u;&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The reason this can&amp;#39;t be translated is the EndsWith call on the FirstName entity property. Since CAML doesn&amp;#39;t support an equivalent in its query language, we can&amp;#39;t provide a translation. There are much more such things that make the parse operation fail, due to the relatively limited expressiveness of CAML. The problem however, especially with big queries, is for developers to get to know where the problem is located exactly. In the previous alphas an InvalidOperationException is thrown with some message, possibly referring to something in the query that couldn&amp;#39;t be translated (e.g. &lt;em&gt;&amp;quot;Unsupported string filtering query expression detected: EndsWith. Only the methods Contains and StartsWith are supported.&amp;quot;&lt;/em&gt;). Although this sample message is pretty easy to understand, there are more complex ones that deserve a better approach.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;&amp;lt;Intermezzo&amp;gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;To put this in a broader context, you should be aware of the fact that &lt;strong&gt;LINQ lacks support for compile-time query validation by custom query providers&lt;/strong&gt;. All the LINQ-capable compilers (C# 3.0, VB 9.0) do, is generating an expression tree representing the query. Therefore, the only way to find out about problems in the query is to execute the code, which triggers the IQueryable-supported (custom query provider&amp;#39;s) query&amp;nbsp;expression tree parser that can signal issues in the query by throwing some exception. All LINQ providers expose such a behavior. As an example, take a look at the following situation in LINQ to SQL:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://community.bartdesmet.net/blogs/linqtosharepoint/WindowsLiveWriter/LINQtoSharePointImprovingtheparserdebugg_4F5F/image.png"&gt;&lt;img style="BORDER-TOP-WIDTH:0px;BORDER-LEFT-WIDTH:0px;BORDER-BOTTOM-WIDTH:0px;BORDER-RIGHT-WIDTH:0px;" height="334" alt="image" src="http://community.bartdesmet.net/blogs/linqtosharepoint/WindowsLiveWriter/LINQtoSharePointImprovingtheparserdebugg_4F5F/image_thumb.png" width="666" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Luckily the message is pretty clear in order to figure out what&amp;#39;s going wrong. Also observe the time when and the place where the exception occurs: not at definition time of the query (the query - i.e. &lt;em&gt;var res = ...&lt;/em&gt; in our case - remains an &lt;em&gt;expression&lt;/em&gt;) but when the iteration &lt;em&gt;statement&lt;/em&gt; is executed.&lt;/p&gt;
&lt;p&gt;&lt;u&gt;Note:&lt;/u&gt; LINQ to SharePoint alpha 0.1 did produce parse errors at query expression definition time instead; this has been fixed in 0.2 so that the query parser isn&amp;#39;t invoked before query execution time (i.e. iteration over the results).&lt;/p&gt;
&lt;p&gt;So what&amp;#39;s wrong with this? Not that much, except for the fact that&amp;nbsp;we would be able to signal such problems &lt;u&gt;at compile time&lt;/u&gt; if we had the appropriate infrastructure in place at the compiler&amp;#39;s side. This would mean that the C# and VB compiler would have to pass the generated expression tree to the custom query provider&amp;#39;s query parser (which could be interfaced for communication with a front-end compiler) as part of the compilation job. Our query parser could then feed a set of&amp;nbsp;warnings and errors&amp;nbsp;back to the compiler, which are then presented to the developer as regular compiler warnings or errors (albeit generated by the custom query provider instead of the compiler itself).&lt;/p&gt;
&lt;p&gt;Since we don&amp;#39;t have such a thing at this very moment, alternatives have to be invented. That&amp;#39;s exactly what we&amp;#39;ve done in LINQ to SharePoint in order to help the developer spot the location of the problem in his/her query.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;&amp;lt;/Intermezzo&amp;gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;So, what&amp;#39;s our approach? Of course we don&amp;#39;t drop the NotSupportedException approach: if your query can&amp;#39;t be translated, you&amp;#39;re&amp;nbsp;out of luck and we need to signal this in some way or another at runtime. However, when debugging we provide a debugger visualizer for LINQ to SharePoint queries that allows you to inspect the query, including the generated CAML. Essentially, the debugger visualizer triggers the parser albeit in a slightly different &amp;quot;&lt;strong&gt;parser run mode&lt;/strong&gt;&amp;quot;: instead of throwing exceptions for parse-time errors, all errors are collected and fed back to the visualizer with enough information to spot the problem. A picture is worth a thousand words, so take a look at this:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://community.bartdesmet.net/blogs/linqtosharepoint/WindowsLiveWriter/LINQtoSharePointImprovingtheparserdebugg_4F5F/image_2.png"&gt;&lt;img style="BORDER-TOP-WIDTH:0px;BORDER-LEFT-WIDTH:0px;BORDER-BOTTOM-WIDTH:0px;BORDER-RIGHT-WIDTH:0px;" height="547" alt="image" src="http://community.bartdesmet.net/blogs/linqtosharepoint/WindowsLiveWriter/LINQtoSharePointImprovingtheparserdebugg_4F5F/image_thumb_2.png" width="639" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;This is the debugger visualizer for LINQ to SharePoint that will become available in a later release (keep an eye on my blog). At the top of the dialog you can see the LINQ query. Admitted, it&amp;#39;s not in its original shape anymore but it&amp;#39;s the best we can do right now (the original LINQ query in either C# 3.0 or VB 9.0 has been eaten by the respective compiler at this stage of execution). The original query looks as follows:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;&lt;font color="#0000ff"&gt;var&lt;/font&gt; res = &lt;font color="#0000ff"&gt;from &lt;/font&gt;t &lt;font color="#0000ff"&gt;in &lt;/font&gt;lst &lt;font color="#0000ff"&gt;where &lt;/font&gt;!(t.FirstName.Contains(&lt;font color="#800000"&gt;&amp;quot;Bart&amp;quot;&lt;/font&gt;) &amp;amp;&amp;amp; t.Age &amp;gt;= 24) || t.LastName.EndsWith(&lt;font color="#800000"&gt;&amp;quot;De Smet&amp;quot;&lt;/font&gt;) &amp;amp;&amp;amp; &lt;font color="#008080"&gt;CamlMethods&lt;/font&gt;.DateRangesOverlap(t.Modified.Value) &lt;font color="#0000ff"&gt;orderby &lt;/font&gt;1 &lt;font color="#0000ff"&gt;select &lt;/font&gt;t;&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The LINQ query you can see in the dialog above is basically the query&amp;#39;s expression tree ToString() call result. With a little knowledge about extension methods and expression trees, you can read such an expression string representation in just a few seconds (as a little exercise play the human compiler, translating a LINQ query to an expression tree followed by a mental ToString-call).&lt;/p&gt;
&lt;p&gt;What the LINQ to SharePoint parser does when running in &amp;quot;&lt;strong&gt;debug mode&lt;/strong&gt;&amp;quot; - in addition to its regular parsing job - is the identification of subexpressions that can&amp;#39;t be translated while continuing the parsing (instead of throwing an exception). All places where something went wrong are marked by &amp;lt;ParseError /&amp;gt; placeholders in the CAML query and each of these have a unique identifier that&amp;#39;s linked (bidirectionally) with the subexpression in the LINQ query that caused the problem. This way, developers can identify problems in a more visually attractive way.&lt;/p&gt;
&lt;p&gt;Even more, in the example above we can see four problems with the query at once. If we&amp;#39;d run the application we&amp;#39;d get only one single exception (which would result in at least four &amp;quot;run-crash-fix&amp;quot; iterations). The goal is to take this to the maximum level possible, providing links from the debugger visualizer to specific help information about the parser issues that occurred (observe the unique identification code on the error, in this case SP0011). In case you&amp;#39;re curious why you&amp;#39;re seeing SP0011 in the fragment above: observe that the t.FirstName.Contains(&amp;quot;Bart&amp;quot;) expression is nested inside a Not expression. CAML doesn&amp;#39;t have a Boolean negation operator in its query schema, so we can&amp;#39;t express the !t.FirstName.Contains(&amp;quot;Bart&amp;quot;) expression as a whole.&lt;/p&gt;
&lt;p&gt;Stay tuned for more LINQ to SharePoint fun soon!&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="0767317B-992E-4b12-91E0-4F059A8CECA8:8dbbca1a-eeeb-4971-a1a6-a3f527fe3cf9" style="PADDING-RIGHT:0px;DISPLAY:inline;PADDING-LEFT:0px;PADDING-BOTTOM:0px;MARGIN:0px;PADDING-TOP:0px;"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/LINQ" rel="tag"&gt;LINQ&lt;/a&gt;, &lt;a href="http://technorati.com/tags/SharePoint" rel="tag"&gt;SharePoint&lt;/a&gt;, &lt;a href="http://technorati.com/tags/CAML" rel="tag"&gt;CAML&lt;/a&gt;, &lt;a href="http://technorati.com/tags/LINQ%20to%20SharePoint" rel="tag"&gt;LINQ to SharePoint&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Orcas" rel="tag"&gt;Orcas&lt;/a&gt;&lt;/div&gt;&lt;img src="http://community.bartdesmet.net/aggbug.aspx?PostID=12585" width="1" height="1"&gt;</description><category domain="http://community.bartdesmet.net/blogs/linqtosharepoint/archive/tags/Tools/default.aspx">Tools</category><category domain="http://community.bartdesmet.net/blogs/linqtosharepoint/archive/tags/Internals/default.aspx">Internals</category></item></channel></rss>