<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"><title type="html">The Great Linq</title><subtitle type="html">Linq insanities</subtitle><id>http://blogs.msdn.com/kfarmer/atom.xml</id><link rel="alternate" type="text/html" href="http://blogs.msdn.com/kfarmer/default.aspx" /><link rel="self" type="application/atom+xml" href="http://blogs.msdn.com/kfarmer/atom.xml" /><generator uri="http://communityserver.org" version="2.1.61025.2">Community Server</generator><updated>2006-03-15T00:31:00Z</updated><entry><title>Departing Microsoft...</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/kfarmer/archive/2008/05/20/departing-microsoft.aspx" /><id>http://blogs.msdn.com/kfarmer/archive/2008/05/20/departing-microsoft.aspx</id><published>2008-05-21T02:39:00Z</published><updated>2008-05-21T02:39:00Z</updated><content type="html">&lt;P&gt;It's taken a while to reach this decision, but Friday will be my last day at Microsoft.&amp;nbsp; I'll be taking a week off (imagine all the housework I can get done...) and starting work at a company where I expect to be working on a lot of R&amp;amp;D and prototypes.&amp;nbsp; It should be interesting, and I hope to be able to play with the bits I spent the last couple years of my life working on.&lt;/P&gt;
&lt;P&gt;As I mentioned in my last post, I'm focussing any blogging efforts at &lt;A href="http://www.thuban.org/"&gt;http://www.thuban.org&lt;/A&gt;.&amp;nbsp; Maybe I'll have something to write about during my week off.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8525330" width="1" height="1"&gt;</content><author><name>kfarmer@microsoft.com</name><uri>http://blogs.msdn.com/members/kfarmer%40microsoft.com.aspx</uri></author></entry><entry><title>Migrating</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/kfarmer/archive/2008/03/26/migrating.aspx" /><id>http://blogs.msdn.com/kfarmer/archive/2008/03/26/migrating.aspx</id><published>2008-03-26T11:23:33Z</published><updated>2008-03-26T11:23:33Z</updated><content type="html">&lt;p&gt;With the release of LINQ, the ASP.NET MVC Preview, and Server 2008 with IIS7, I've finally gotten over the web-developer's block that has prevented me from porting my old website off of Zope.&lt;/p&gt;  &lt;p&gt;So I'll be posting to &lt;a href="http://www.thuban.org"&gt;my revised website&lt;/a&gt; from now on.&amp;#160; It'll let me play around more with the new toys, including Silverlight.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8337438" width="1" height="1"&gt;</content><author><name>kfarmer@microsoft.com</name><uri>http://blogs.msdn.com/members/kfarmer%40microsoft.com.aspx</uri></author></entry><entry><title>Where(prototype)</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/kfarmer/archive/2007/11/19/where-prototype.aspx" /><id>http://blogs.msdn.com/kfarmer/archive/2007/11/19/where-prototype.aspx</id><published>2007-11-19T13:20:16Z</published><updated>2007-11-19T13:20:16Z</updated><content type="html">&lt;p&gt;Just something I decided to try cobbling together tonight.&amp;nbsp; Didn't take more than a few minutes, trying to type quietly (didn't want to wake anyone).&lt;/p&gt; &lt;p&gt;It allows you to do things like:&lt;/p&gt;&lt;pre class="code"&gt;        &lt;span style="color: rgb(0,0,255)"&gt;var&lt;/span&gt; q = db.Customers.Where(&lt;span style="color: rgb(0,0,255)"&gt;new&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;Customer&lt;/span&gt; { CustomerID = &lt;span style="color: rgb(163,21,21)"&gt;"EASTC"&lt;/span&gt; });&lt;/pre&gt;&lt;pre class="code"&gt;&lt;/pre&gt;
&lt;p&gt;Basically, it's a where-by-prototype. One obvious function, as seen above, is to get a LINQ to SQL entity by ID.&lt;/p&gt;
&lt;p&gt;Here's the code:&lt;/p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;pre class="code"&gt;        &lt;span style="color: rgb(0,0,255)"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;static&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;IQueryable&lt;/span&gt;&amp;lt;TEntity&amp;gt; Where&amp;lt;TEntity&amp;gt;(&lt;br&gt;                &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;IQueryable&lt;/span&gt;&amp;lt;TEntity&amp;gt; seq, TEntity entity&lt;br&gt;                )
        {
            &lt;span style="color: rgb(43,145,175)"&gt;IQueryable&lt;/span&gt;&amp;lt;TEntity&amp;gt; result = seq;
            &lt;span style="color: rgb(0,0,255)"&gt;var&lt;/span&gt; memberTypes = &lt;span style="color: rgb(0,0,255)"&gt;new&lt;/span&gt;[] { &lt;span style="color: rgb(43,145,175)"&gt;MemberTypes&lt;/span&gt;.Property, &lt;span style="color: rgb(43,145,175)"&gt;MemberTypes&lt;/span&gt;.Field };

            &lt;span style="color: rgb(0,0,255)"&gt;var&lt;/span&gt; members = &lt;span style="color: rgb(0,0,255)"&gt;typeof&lt;/span&gt;(TEntity).GetMembers()&lt;br&gt;                          .Where(mi =&amp;gt; memberTypes.Contains(mi.MemberType) &lt;br&gt;                                       &amp;amp;&amp;amp; mi.GetCustomAttributes(&lt;span style="color: rgb(0,0,255)"&gt;typeof&lt;/span&gt;(&lt;span style="color: rgb(43,145,175)"&gt;ColumnAttribute&lt;/span&gt;), &lt;span style="color: rgb(0,0,255)"&gt;true&lt;/span&gt;)&lt;br&gt;                                       .Length &amp;gt; 0);

            &lt;span style="color: rgb(0,0,255)"&gt;foreach&lt;/span&gt; (&lt;span style="color: rgb(0,0,255)"&gt;var&lt;/span&gt; member &lt;span style="color: rgb(0,0,255)"&gt;in&lt;/span&gt; members)
            {
                &lt;span style="color: rgb(0,0,255)"&gt;var&lt;/span&gt; isField = member.MemberType == &lt;span style="color: rgb(43,145,175)"&gt;MemberTypes&lt;/span&gt;.Field;
                &lt;span style="color: rgb(0,0,255)"&gt;var&lt;/span&gt; memberAsField = member &lt;span style="color: rgb(0,0,255)"&gt;as&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;FieldInfo&lt;/span&gt;;
                &lt;span style="color: rgb(0,0,255)"&gt;var&lt;/span&gt; memberAsProperty = member &lt;span style="color: rgb(0,0,255)"&gt;as&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;PropertyInfo&lt;/span&gt;;

                &lt;span style="color: rgb(0,0,255)"&gt;var&lt;/span&gt; memberValue = isField ? memberAsField.GetValue(entity) &lt;br&gt;                                          : memberAsProperty.GetValue(entity, &lt;span style="color: rgb(0,0,255)"&gt;null&lt;/span&gt;);
                &lt;span style="color: rgb(0,0,255)"&gt;var&lt;/span&gt; memberIsRefType = (isField ? memberAsField.FieldType &lt;br&gt;                                               : memberAsProperty.PropertyType&lt;br&gt;                                      ).IsClass;

                &lt;span style="color: rgb(0,0,255)"&gt;var&lt;/span&gt; memberIsDefaultValue = (memberValue == (memberIsRefType ? (&lt;span style="color: rgb(0,0,255)"&gt;object&lt;/span&gt;)&lt;span style="color: rgb(0,0,255)"&gt;null&lt;/span&gt; &lt;br&gt;                                                                            : (&lt;span style="color: rgb(0,0,255)"&gt;object&lt;/span&gt;)0&lt;br&gt;                                                           ));

                &lt;span style="color: rgb(0,0,255)"&gt;if&lt;/span&gt; (memberIsDefaultValue)
                {
                    &lt;span style="color: rgb(0,0,255)"&gt;continue&lt;/span&gt;;
                }

                &lt;span style="color: rgb(0,0,255)"&gt;var&lt;/span&gt; parameter = &lt;span style="color: rgb(43,145,175)"&gt;Expression&lt;/span&gt;.Parameter(&lt;span style="color: rgb(0,0,255)"&gt;typeof&lt;/span&gt;(TEntity), &lt;span style="color: rgb(163,21,21)"&gt;"p"&lt;/span&gt;);

                &lt;span style="color: rgb(0,0,255)"&gt;var&lt;/span&gt; memberAccess = &lt;span style="color: rgb(43,145,175)"&gt;Expression&lt;/span&gt;.MakeMemberAccess(parameter, member);
                &lt;span style="color: rgb(0,0,255)"&gt;var&lt;/span&gt; value = &lt;span style="color: rgb(43,145,175)"&gt;Expression&lt;/span&gt;.Constant(memberValue);
                &lt;span style="color: rgb(0,0,255)"&gt;var&lt;/span&gt; equality = &lt;span style="color: rgb(43,145,175)"&gt;Expression&lt;/span&gt;.Equal(memberAccess, value);

                &lt;span style="color: rgb(0,0,255)"&gt;var&lt;/span&gt; predicate = &lt;span style="color: rgb(43,145,175)"&gt;Expression&lt;/span&gt;.Lambda&amp;lt;&lt;span style="color: rgb(43,145,175)"&gt;Func&lt;/span&gt;&amp;lt;TEntity, &lt;span style="color: rgb(0,0,255)"&gt;bool&lt;/span&gt;&amp;gt;&amp;gt;(equality, parameter);

                result = result.Where(predicate);
            }

            &lt;span style="color: rgb(0,0,255)"&gt;return&lt;/span&gt; result;
        }&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=6395861" width="1" height="1"&gt;</content><author><name>kfarmer@microsoft.com</name><uri>http://blogs.msdn.com/members/kfarmer%40microsoft.com.aspx</uri></author></entry><entry><title>Encapsulation and LINQ to SQL</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/kfarmer/archive/2007/11/13/encapsulation-and-linq-to-sql.aspx" /><id>http://blogs.msdn.com/kfarmer/archive/2007/11/13/encapsulation-and-linq-to-sql.aspx</id><published>2007-11-14T10:34:43Z</published><updated>2007-11-14T10:34:43Z</updated><content type="html">&lt;p&gt;In my &lt;a href="http://blogs.msdn.com/kfarmer/archive/2007/11/06/linq-and-3-tier-dogma.aspx"&gt;last post&lt;/a&gt; I rendered some opinions on how to approach using LINQ to SQL in an encapsulated manner.&amp;#160; In response, several folks requested I put together some more concrete examples.&amp;#160; I have now done so.&amp;#160; Pardon the high code-to-text ratio: I'm not feeling particularly poetic at the moment.&amp;#160; I also just wrote this code up, so it hasn't had anything more than trivial testing.&amp;#160; But, as a place to get people started it's as good as any at the moment.&lt;/p&gt;  &lt;h1&gt;TableView&lt;/h1&gt;  &lt;p&gt;The TableView class encapsulates an IQueryable constructed by applying a predicate filter to a Table.&amp;#160; This enables the pattern of client-side row restriction by way of forcing WHERE constraints in the generated SQL.&amp;#160; For example, permitting the retrieval of only those customers residing in London:&lt;/p&gt;  &lt;blockquote&gt;   &lt;pre class="code"&gt;&lt;span style="color: rgb(0,0,255)"&gt;var&lt;/span&gt; tableView = &lt;span style="color: rgb(0,0,255)"&gt;new&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;TableView&lt;/span&gt;&amp;lt;&lt;span style="color: rgb(43,145,175)"&gt;Customer&lt;/span&gt;&amp;gt;(dataContext, c =&amp;gt; c.City == &lt;span style="color: rgb(163,21,21)"&gt;&amp;quot;London&amp;quot;&lt;/span&gt;);&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;It includes a subset of the functionality of Table, including Attach, Insert and Delete, which it forwards to the encapsulated table provided the entities in question pass the filter.&lt;/p&gt;

&lt;h2&gt;TableView.cs&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;pre class="code"&gt;&lt;span style="color: rgb(0,0,255)"&gt;using&lt;/span&gt; System;
&lt;span style="color: rgb(0,0,255)"&gt;using&lt;/span&gt; System.Collections.Generic;
&lt;span style="color: rgb(0,0,255)"&gt;using&lt;/span&gt; System.Data.Linq;
&lt;span style="color: rgb(0,0,255)"&gt;using&lt;/span&gt; System.Linq;
&lt;span style="color: rgb(0,0,255)"&gt;using&lt;/span&gt; System.Linq.Expressions;

&lt;span style="color: rgb(0,0,255)"&gt;namespace&lt;/span&gt; Thuban.Data.Linq
{
    &lt;span style="color: rgb(0,0,255)"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;sealed&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;class&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;TableView&lt;/span&gt;&amp;lt;TEntity&amp;gt; : &lt;span style="color: rgb(43,145,175)"&gt;IQueryable&lt;/span&gt;&amp;lt;TEntity&amp;gt;, &lt;span style="color: rgb(43,145,175)"&gt;ITable
&lt;/span&gt;        &lt;span style="color: rgb(0,0,255)"&gt;where&lt;/span&gt; TEntity : &lt;span style="color: rgb(0,0,255)"&gt;class
&lt;/span&gt;    {
        &lt;span style="color: rgb(43,145,175)"&gt;IQueryable&lt;/span&gt;&amp;lt;TEntity&amp;gt; baseQuery;
        &lt;span style="color: rgb(43,145,175)"&gt;Table&lt;/span&gt;&amp;lt;TEntity&amp;gt; table;
        &lt;span style="color: rgb(43,145,175)"&gt;Func&lt;/span&gt;&amp;lt;TEntity, &lt;span style="color: rgb(0,0,255)"&gt;bool&lt;/span&gt;&amp;gt; predicate;

        &lt;span style="color: rgb(0,0,255)"&gt;public&lt;/span&gt; TableView(&lt;span style="color: rgb(43,145,175)"&gt;DataContext&lt;/span&gt; dataContext, &lt;span style="color: rgb(43,145,175)"&gt;Expression&lt;/span&gt;&amp;lt;&lt;span style="color: rgb(43,145,175)"&gt;Func&lt;/span&gt;&amp;lt;TEntity, &lt;span style="color: rgb(0,0,255)"&gt;bool&lt;/span&gt;&amp;gt;&amp;gt; predicate)
        {
            &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.table = dataContext.GetTable&amp;lt;TEntity&amp;gt;();
            &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.baseQuery = table.Where(predicate);
            &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.predicate = predicate.Compile();
        }

&lt;span style="color: rgb(0,0,255)"&gt;        #region&lt;/span&gt; IEnumerable&amp;lt;TEntity&amp;gt; Members

        &lt;span style="color: rgb(0,0,255)"&gt;public&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;IEnumerator&lt;/span&gt;&amp;lt;TEntity&amp;gt; GetEnumerator()
        {
            &lt;span style="color: rgb(0,0,255)"&gt;return&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.baseQuery.GetEnumerator();
        }

&lt;span style="color: rgb(0,0,255)"&gt;        #endregion

        #region&lt;/span&gt; IEnumerable Members

        System.Collections.&lt;span style="color: rgb(43,145,175)"&gt;IEnumerator&lt;/span&gt; System.Collections.&lt;span style="color: rgb(43,145,175)"&gt;IEnumerable&lt;/span&gt;.GetEnumerator()
        {
            &lt;span style="color: rgb(0,0,255)"&gt;return&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.GetEnumerator();
        }

&lt;span style="color: rgb(0,0,255)"&gt;        #endregion

        #region&lt;/span&gt; PermissionChecks

        &lt;span style="color: rgb(0,0,255)"&gt;internal&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; PermissionCheck(&lt;span style="color: rgb(43,145,175)"&gt;Action&lt;/span&gt;&amp;lt;TEntity&amp;gt; action, TEntity entity)
        {
            &lt;span style="color: rgb(0,0,255)"&gt;if&lt;/span&gt; (predicate(entity))
            {
                action(entity);
            }
            &lt;span style="color: rgb(0,0,255)"&gt;else
&lt;/span&gt;            {
                &lt;span style="color: rgb(0,0,255)"&gt;throw&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;new&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;InvalidOperationException&lt;/span&gt;(&lt;span style="color: rgb(163,21,21)"&gt;&amp;quot;No permission&amp;quot;&lt;/span&gt;);
            }
        }

        &lt;span style="color: rgb(0,0,255)"&gt;internal&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; PermissionCheck(&lt;span style="color: rgb(43,145,175)"&gt;Action&lt;/span&gt;&amp;lt;TEntity, TEntity&amp;gt; action, TEntity entity1, TEntity entity2)
        {
            &lt;span style="color: rgb(0,0,255)"&gt;if&lt;/span&gt; (predicate(entity1) &amp;amp;&amp;amp; predicate(entity2))
            {
                action(entity1, entity2);
            }
            &lt;span style="color: rgb(0,0,255)"&gt;else
&lt;/span&gt;            {
                &lt;span style="color: rgb(0,0,255)"&gt;throw&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;new&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;InvalidOperationException&lt;/span&gt;(&lt;span style="color: rgb(163,21,21)"&gt;&amp;quot;No permission&amp;quot;&lt;/span&gt;);
            }
        }

        &lt;span style="color: rgb(0,0,255)"&gt;internal&lt;/span&gt; TResult PermissionCheck&amp;lt;TResult&amp;gt;(&lt;span style="color: rgb(43,145,175)"&gt;Func&lt;/span&gt;&amp;lt;TEntity, TResult&amp;gt; function, TEntity entity)
        {
            &lt;span style="color: rgb(0,0,255)"&gt;if&lt;/span&gt; (predicate(entity))
            {
                &lt;span style="color: rgb(0,0,255)"&gt;return&lt;/span&gt; function(entity);
            }
            &lt;span style="color: rgb(0,0,255)"&gt;else
&lt;/span&gt;            {
                &lt;span style="color: rgb(0,0,255)"&gt;throw&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;new&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;InvalidOperationException&lt;/span&gt;(&lt;span style="color: rgb(163,21,21)"&gt;&amp;quot;No permission&amp;quot;&lt;/span&gt;);
            }
        }

        &lt;span style="color: rgb(0,0,255)"&gt;internal&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; PermissionCheck(&lt;span style="color: rgb(43,145,175)"&gt;Action&lt;/span&gt;&amp;lt;&lt;span style="color: rgb(43,145,175)"&gt;IEnumerable&lt;/span&gt;&amp;lt;TEntity&amp;gt;&amp;gt; action, &lt;span style="color: rgb(43,145,175)"&gt;IEnumerable&lt;/span&gt;&amp;lt;TEntity&amp;gt; entities)
        {
            &lt;span style="color: rgb(0,0,255)"&gt;if&lt;/span&gt; (entities.All(predicate))
            {
                action(entities);
            }
            &lt;span style="color: rgb(0,0,255)"&gt;else
&lt;/span&gt;            {
                &lt;span style="color: rgb(0,0,255)"&gt;throw&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;new&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;InvalidOperationException&lt;/span&gt;(&lt;span style="color: rgb(163,21,21)"&gt;&amp;quot;No permission&amp;quot;&lt;/span&gt;);
            }
        }
        
&lt;span style="color: rgb(0,0,255)"&gt;        #endregion

        #region&lt;/span&gt; FilteredTable&amp;lt;TEntity&amp;gt; Members

        &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; Attach(TEntity entity, TEntity original)
        {
            PermissionCheck((x, y) =&amp;gt; table.Attach(x, y), entity, original);
        }

        &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; Attach(TEntity entity, &lt;span style="color: rgb(0,0,255)"&gt;bool&lt;/span&gt; asModified)
        {
            PermissionCheck(x =&amp;gt; table.Attach(x, asModified), entity);
        }

        &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; Attach(TEntity entity)
        {
            PermissionCheck(x =&amp;gt; table.Attach(x), entity);
        }

        &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; AttachAll(&lt;span style="color: rgb(43,145,175)"&gt;IEnumerable&lt;/span&gt;&amp;lt;TEntity&amp;gt; entities, &lt;span style="color: rgb(0,0,255)"&gt;bool&lt;/span&gt; asModified)
        {
            PermissionCheck(x =&amp;gt; table.AttachAll(x, asModified), entities);
        }

        &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; AttachAll(&lt;span style="color: rgb(43,145,175)"&gt;IEnumerable&lt;/span&gt;&amp;lt;TEntity&amp;gt; entities)
        {
            PermissionCheck(x =&amp;gt; table.AttachAll(x), entities);
        }

        &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; DeleteAllOnSubmit(&lt;span style="color: rgb(43,145,175)"&gt;IEnumerable&lt;/span&gt;&amp;lt;TEntity&amp;gt; entities)
        {
            PermissionCheck(x =&amp;gt; table.DeleteAllOnSubmit(x), entities);
        }

        &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; DeleteOnSubmit(TEntity entity)
        {
            PermissionCheck(x =&amp;gt; table.DeleteOnSubmit(x), entity);
        }

        &lt;span style="color: rgb(43,145,175)"&gt;ModifiedMemberInfo&lt;/span&gt;[] GetModifiedMembers(TEntity entity)
        {
            &lt;span style="color: rgb(0,0,255)"&gt;return&lt;/span&gt; PermissionCheck(x =&amp;gt; table.GetModifiedMembers(x), entity);
        }

        TEntity GetOriginalEntityState(TEntity entity)
        {
            &lt;span style="color: rgb(0,0,255)"&gt;return&lt;/span&gt; PermissionCheck(x =&amp;gt; table.GetOriginalEntityState(x), entity);
        }

        &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; InsertAllOnSubmit(&lt;span style="color: rgb(43,145,175)"&gt;IEnumerable&lt;/span&gt;&amp;lt;TEntity&amp;gt; entities)
        {
            PermissionCheck(x =&amp;gt; table.InsertAllOnSubmit(x), entities);
        }

        &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; InsertOnSubmit(TEntity entity)
        {
            PermissionCheck(x =&amp;gt; table.InsertOnSubmit(x), entity);
        }

&lt;span style="color: rgb(0,0,255)"&gt;        #endregion

        #region&lt;/span&gt; ITable Members

        &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;ITable&lt;/span&gt;.Attach(&lt;span style="color: rgb(0,0,255)"&gt;object&lt;/span&gt; entity, &lt;span style="color: rgb(0,0,255)"&gt;object&lt;/span&gt; original)
        {
            &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.Attach((TEntity)entity, (TEntity)original);
        }

        &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;ITable&lt;/span&gt;.Attach(&lt;span style="color: rgb(0,0,255)"&gt;object&lt;/span&gt; entity, &lt;span style="color: rgb(0,0,255)"&gt;bool&lt;/span&gt; asModified)
        {
            &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.Attach((TEntity)entity, asModified);
        }

        &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;ITable&lt;/span&gt;.Attach(&lt;span style="color: rgb(0,0,255)"&gt;object&lt;/span&gt; entity)
        {
            &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.Attach((TEntity)entity);
        }

        &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;ITable&lt;/span&gt;.AttachAll(System.Collections.&lt;span style="color: rgb(43,145,175)"&gt;IEnumerable&lt;/span&gt; entities, &lt;span style="color: rgb(0,0,255)"&gt;bool&lt;/span&gt; asModified)
        {
            &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.AttachAll(entities.Cast&amp;lt;TEntity&amp;gt;(), asModified);
        }

        &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;ITable&lt;/span&gt;.AttachAll(System.Collections.&lt;span style="color: rgb(43,145,175)"&gt;IEnumerable&lt;/span&gt; entities)
        {
            &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.AttachAll(entities.Cast&amp;lt;TEntity&amp;gt;());
        }

        &lt;span style="color: rgb(43,145,175)"&gt;DataContext&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;ITable&lt;/span&gt;.Context
        {
            &lt;span style="color: rgb(0,0,255)"&gt;get&lt;/span&gt; { &lt;span style="color: rgb(0,0,255)"&gt;throw&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;new&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;InvalidOperationException&lt;/span&gt;(&lt;span style="color: rgb(163,21,21)"&gt;&amp;quot;Access to the underlying context is not allowed.&amp;quot;&lt;/span&gt;); }
        }

        &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;ITable&lt;/span&gt;.DeleteAllOnSubmit(System.Collections.&lt;span style="color: rgb(43,145,175)"&gt;IEnumerable&lt;/span&gt; entities)
        {
            &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.DeleteAllOnSubmit(entities.Cast&amp;lt;TEntity&amp;gt;());
        }

        &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;ITable&lt;/span&gt;.DeleteOnSubmit(&lt;span style="color: rgb(0,0,255)"&gt;object&lt;/span&gt; entity)
        {
            &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.DeleteOnSubmit((TEntity)entity);
        }

        &lt;span style="color: rgb(43,145,175)"&gt;ModifiedMemberInfo&lt;/span&gt;[] &lt;span style="color: rgb(43,145,175)"&gt;ITable&lt;/span&gt;.GetModifiedMembers(&lt;span style="color: rgb(0,0,255)"&gt;object&lt;/span&gt; entity)
        {
            &lt;span style="color: rgb(0,0,255)"&gt;return&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.GetModifiedMembers((TEntity)entity);
        }

        &lt;span style="color: rgb(0,0,255)"&gt;object&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;ITable&lt;/span&gt;.GetOriginalEntityState(&lt;span style="color: rgb(0,0,255)"&gt;object&lt;/span&gt; entity)
        {
            &lt;span style="color: rgb(0,0,255)"&gt;return&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.GetOriginalEntityState((TEntity)entity);
        }

        &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;ITable&lt;/span&gt;.InsertAllOnSubmit(System.Collections.&lt;span style="color: rgb(43,145,175)"&gt;IEnumerable&lt;/span&gt; entities)
        {
            &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.InsertAllOnSubmit(entities.Cast&amp;lt;TEntity&amp;gt;());
        }

        &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;ITable&lt;/span&gt;.InsertOnSubmit(&lt;span style="color: rgb(0,0,255)"&gt;object&lt;/span&gt; entity)
        {
            &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.InsertOnSubmit((TEntity)entity);
        }

        &lt;span style="color: rgb(0,0,255)"&gt;bool&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;ITable&lt;/span&gt;.IsReadOnly
        {
            &lt;span style="color: rgb(0,0,255)"&gt;get&lt;/span&gt; { &lt;span style="color: rgb(0,0,255)"&gt;return&lt;/span&gt; table.IsReadOnly; }
        }

&lt;span style="color: rgb(0,0,255)"&gt;        #endregion

        #region&lt;/span&gt; IQueryable Members

        &lt;span style="color: rgb(43,145,175)"&gt;Type&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;IQueryable&lt;/span&gt;.ElementType
        {
            &lt;span style="color: rgb(0,0,255)"&gt;get&lt;/span&gt; { &lt;span style="color: rgb(0,0,255)"&gt;return&lt;/span&gt; baseQuery.ElementType; }
        }

        &lt;span style="color: rgb(43,145,175)"&gt;Expression&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;IQueryable&lt;/span&gt;.Expression
        {
            &lt;span style="color: rgb(0,0,255)"&gt;get&lt;/span&gt; { &lt;span style="color: rgb(0,0,255)"&gt;return&lt;/span&gt; baseQuery.Expression; }
        }

        &lt;span style="color: rgb(43,145,175)"&gt;IQueryProvider&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;IQueryable&lt;/span&gt;.Provider
        {
            &lt;span style="color: rgb(0,0,255)"&gt;get&lt;/span&gt; { &lt;span style="color: rgb(0,0,255)"&gt;return&lt;/span&gt; baseQuery.Provider; }
        }

&lt;span style="color: rgb(0,0,255)"&gt;        #endregion
&lt;/span&gt;    }
}&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;h1&gt;DataContextWrapper&lt;/h1&gt;

&lt;p&gt;The other type I've worked on is the abstract class, DataContextWrapper.&amp;#160; As TableView does for Table, it encapsulates and provides a subset of the original's function.&amp;#160; In particular, it includes a hook for table initialization (not entirely hashed out, to be sure -- I haven't added support for UDFs).&amp;#160; I've surfaced some properties of the underlying data context where I thought (quickly) that it made sense to do so, such as CommandTimeout, SubmitChanges, and strongly-typed versions of Refresh; I omitted Log since it's primarily for debugging, and not necessarily appropriate for end-user consumption in this situation.&amp;#160; I've also implemented the dispose pattern, and provided a helper method to create a new TableView, for use in the GetQuery(type) initialization hook.&amp;#160; Of the two -- TableView and DataContextWrapper -- this is the more primitive.&lt;/p&gt;

&lt;h2&gt;DataContextWrapper.cs&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;pre class="code"&gt;&lt;span style="color: rgb(0,0,255)"&gt;using&lt;/span&gt; System;
&lt;span style="color: rgb(0,0,255)"&gt;using&lt;/span&gt; System.Collections.Generic;
&lt;span style="color: rgb(0,0,255)"&gt;using&lt;/span&gt; System.Data.Linq;
&lt;span style="color: rgb(0,0,255)"&gt;using&lt;/span&gt; System.Linq;
&lt;span style="color: rgb(0,0,255)"&gt;using&lt;/span&gt; System.Linq.Expressions;
&lt;span style="color: rgb(0,0,255)"&gt;using&lt;/span&gt; System.Reflection;

&lt;span style="color: rgb(0,0,255)"&gt;namespace&lt;/span&gt; Thuban.Data.Linq
{
    &lt;span style="color: rgb(0,0,255)"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;abstract&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;class&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;DataContextWrapper&lt;/span&gt; : &lt;span style="color: rgb(43,145,175)"&gt;IDisposable
&lt;/span&gt;    {
        &lt;span style="color: rgb(0,0,255)"&gt;protected&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;DataContext&lt;/span&gt; DataContext { &lt;span style="color: rgb(0,0,255)"&gt;get&lt;/span&gt;; &lt;span style="color: rgb(0,0,255)"&gt;private&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;set&lt;/span&gt;; }
        &lt;span style="color: rgb(0,0,255)"&gt;protected&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;bool&lt;/span&gt; IsDisposed { &lt;span style="color: rgb(0,0,255)"&gt;get&lt;/span&gt;; &lt;span style="color: rgb(0,0,255)"&gt;private&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;set&lt;/span&gt;; }

        &lt;span style="color: rgb(43,145,175)"&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style="color: rgb(43,145,175)"&gt;Type&lt;/span&gt;, &lt;span style="color: rgb(0,0,255)"&gt;object&lt;/span&gt;&amp;gt; tables = &lt;span style="color: rgb(0,0,255)"&gt;new&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style="color: rgb(43,145,175)"&gt;Type&lt;/span&gt;, &lt;span style="color: rgb(0,0,255)"&gt;object&lt;/span&gt;&amp;gt;();

        &lt;span style="color: rgb(0,0,255)"&gt;protected&lt;/span&gt; DataContextWrapper(&lt;span style="color: rgb(43,145,175)"&gt;DataContext&lt;/span&gt; dataContext)
        {
            &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.DataContext = dataContext;

            &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.InitializeTables();
        }

        &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; InitializeTables()
        {
            CheckDisposed();

            &lt;span style="color: rgb(0,0,255)"&gt;var&lt;/span&gt; filteredTableFields =
                &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.GetType()
                .GetFields(&lt;span style="color: rgb(43,145,175)"&gt;BindingFlags&lt;/span&gt;.Public | &lt;span style="color: rgb(43,145,175)"&gt;BindingFlags&lt;/span&gt;.Instance)
                .Where(fi =&amp;gt; fi.FieldType.GetGenericTypeDefinition() == &lt;span style="color: rgb(0,0,255)"&gt;typeof&lt;/span&gt;(&lt;span style="color: rgb(43,145,175)"&gt;TableView&lt;/span&gt;&amp;lt;&amp;gt;));

            &lt;span style="color: rgb(0,0,255)"&gt;foreach&lt;/span&gt; (&lt;span style="color: rgb(0,0,255)"&gt;var&lt;/span&gt; filteredTableField &lt;span style="color: rgb(0,0,255)"&gt;in&lt;/span&gt; filteredTableFields)
            {
                &lt;span style="color: rgb(0,0,255)"&gt;var&lt;/span&gt; type = filteredTableField.FieldType.GetGenericArguments()[0];

                &lt;span style="color: rgb(0,0,255)"&gt;var&lt;/span&gt; getTable = &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.GetType().GetMethod(&lt;span style="color: rgb(163,21,21)"&gt;&amp;quot;GetTable&amp;quot;&lt;/span&gt;).MakeGenericMethod(type);

                &lt;span style="color: rgb(0,0,255)"&gt;var&lt;/span&gt; table = getTable.Invoke(&lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;, &lt;span style="color: rgb(0,0,255)"&gt;null&lt;/span&gt;);

                filteredTableField.SetValue(&lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;, table);
            }
        }

&lt;span style="color: rgb(0,0,255)"&gt;        #region&lt;/span&gt; Abstract Methods

        &lt;span style="color: rgb(0,0,255)"&gt;protected&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;abstract&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;IQueryable&lt;/span&gt; GetQuery(&lt;span style="color: rgb(43,145,175)"&gt;Type&lt;/span&gt; entityType);

&lt;span style="color: rgb(0,0,255)"&gt;        #endregion

        #region&lt;/span&gt; Helpers

        &lt;span style="color: rgb(0,0,255)"&gt;protected&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;TableView&lt;/span&gt;&amp;lt;TEntity&amp;gt; CreateTableView&amp;lt;TEntity&amp;gt;(&lt;span style="color: rgb(43,145,175)"&gt;Expression&lt;/span&gt;&amp;lt;&lt;span style="color: rgb(43,145,175)"&gt;Func&lt;/span&gt;&amp;lt;TEntity, &lt;span style="color: rgb(0,0,255)"&gt;bool&lt;/span&gt;&amp;gt;&amp;gt; predicate)
            &lt;span style="color: rgb(0,0,255)"&gt;where&lt;/span&gt; TEntity : &lt;span style="color: rgb(0,0,255)"&gt;class
&lt;/span&gt;        {
            &lt;span style="color: rgb(0,0,255)"&gt;return&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;new&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;TableView&lt;/span&gt;&amp;lt;TEntity&amp;gt;(&lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.DataContext, predicate);
        }

&lt;span style="color: rgb(0,0,255)"&gt;        #endregion

        #region&lt;/span&gt; DataContext Analogues

        &lt;span style="color: rgb(0,0,255)"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;int&lt;/span&gt; CommandTimeout
        {
            &lt;span style="color: rgb(0,0,255)"&gt;get
&lt;/span&gt;            {
                &lt;span style="color: rgb(0,0,255)"&gt;return&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.DataContext.CommandTimeout;
            }
            &lt;span style="color: rgb(0,0,255)"&gt;set
&lt;/span&gt;            {
                &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.DataContext.CommandTimeout = &lt;span style="color: rgb(0,0,255)"&gt;value&lt;/span&gt;;
            }
        }

        &lt;span style="color: rgb(0,0,255)"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; SubmitChanges()
        {
            &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.DataContext.SubmitChanges();
        }

        &lt;span style="color: rgb(0,0,255)"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; SubmitChanges(&lt;span style="color: rgb(43,145,175)"&gt;ConflictMode&lt;/span&gt; conflictMode)
        {
            &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.DataContext.SubmitChanges(conflictMode);
        }

        &lt;span style="color: rgb(0,0,255)"&gt;public&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;TableView&lt;/span&gt;&amp;lt;TEntity&amp;gt; GetTable&amp;lt;TEntity&amp;gt;()
            &lt;span style="color: rgb(0,0,255)"&gt;where&lt;/span&gt; TEntity : &lt;span style="color: rgb(0,0,255)"&gt;class
&lt;/span&gt;        {
            CheckDisposed();

            &lt;span style="color: rgb(0,0,255)"&gt;if&lt;/span&gt; (tables.Keys.Contains(&lt;span style="color: rgb(0,0,255)"&gt;typeof&lt;/span&gt;(TEntity)))
            {
                &lt;span style="color: rgb(0,0,255)"&gt;return&lt;/span&gt; (&lt;span style="color: rgb(43,145,175)"&gt;TableView&lt;/span&gt;&amp;lt;TEntity&amp;gt;)tables[&lt;span style="color: rgb(0,0,255)"&gt;typeof&lt;/span&gt;(TEntity)];
            }

            &lt;span style="color: rgb(0,0,255)"&gt;var&lt;/span&gt; query = &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.GetQuery(&lt;span style="color: rgb(0,0,255)"&gt;typeof&lt;/span&gt;(TEntity));

            &lt;span style="color: rgb(0,0,255)"&gt;if&lt;/span&gt; (query == &lt;span style="color: rgb(0,0,255)"&gt;null&lt;/span&gt;)
            {
                &lt;span style="color: rgb(0,0,255)"&gt;throw&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;new&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;InvalidOperationException&lt;/span&gt;(&lt;span style="color: rgb(163,21,21)"&gt;&amp;quot;Table of type '&amp;quot;&lt;/span&gt; + &lt;span style="color: rgb(0,0,255)"&gt;typeof&lt;/span&gt;(TEntity).Name + &lt;span style="color: rgb(163,21,21)"&gt;&amp;quot;' does not have a defined query.&amp;quot;&lt;/span&gt;);
            }
            &lt;span style="color: rgb(0,0,255)"&gt;else
&lt;/span&gt;            {
                tables.Add(&lt;span style="color: rgb(0,0,255)"&gt;typeof&lt;/span&gt;(TEntity), (&lt;span style="color: rgb(43,145,175)"&gt;TableView&lt;/span&gt;&amp;lt;TEntity&amp;gt;)query);

                &lt;span style="color: rgb(0,0,255)"&gt;return&lt;/span&gt; (&lt;span style="color: rgb(43,145,175)"&gt;TableView&lt;/span&gt;&amp;lt;TEntity&amp;gt;)tables[&lt;span style="color: rgb(0,0,255)"&gt;typeof&lt;/span&gt;(TEntity)];
            }
        }

        &lt;span style="color: rgb(0,0,255)"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; Refresh&amp;lt;TEntity&amp;gt;(&lt;span style="color: rgb(43,145,175)"&gt;RefreshMode&lt;/span&gt; refreshMode, TEntity entity)
            &lt;span style="color: rgb(0,0,255)"&gt;where&lt;/span&gt; TEntity : &lt;span style="color: rgb(0,0,255)"&gt;class
&lt;/span&gt;        {
            &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.GetTable&amp;lt;TEntity&amp;gt;().PermissionCheck(x =&amp;gt; &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.DataContext.Refresh(refreshMode, x), entity);
        }

        &lt;span style="color: rgb(0,0,255)"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; Refresh&amp;lt;TEntity&amp;gt;(&lt;span style="color: rgb(43,145,175)"&gt;RefreshMode&lt;/span&gt; refreshMode, &lt;span style="color: rgb(43,145,175)"&gt;IEnumerable&lt;/span&gt;&amp;lt;TEntity&amp;gt; entities)
            &lt;span style="color: rgb(0,0,255)"&gt;where&lt;/span&gt; TEntity : &lt;span style="color: rgb(0,0,255)"&gt;class
&lt;/span&gt;        {
            &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.GetTable&amp;lt;TEntity&amp;gt;().PermissionCheck(x =&amp;gt; &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.Refresh(refreshMode, x), entities);
        }

        &lt;span style="color: rgb(0,0,255)"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; Refresh&amp;lt;TEntity&amp;gt;(&lt;span style="color: rgb(43,145,175)"&gt;RefreshMode&lt;/span&gt; refreshMode, &lt;span style="color: rgb(0,0,255)"&gt;params&lt;/span&gt; TEntity[] entities)
            &lt;span style="color: rgb(0,0,255)"&gt;where&lt;/span&gt; TEntity : &lt;span style="color: rgb(0,0,255)"&gt;class
&lt;/span&gt;        {
            &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.Refresh(refreshMode, (&lt;span style="color: rgb(43,145,175)"&gt;IEnumerable&lt;/span&gt;&amp;lt;TEntity&amp;gt;)entities);
        }

&lt;span style="color: rgb(0,0,255)"&gt;        #endregion

        #region&lt;/span&gt; IDisposable Members

        &lt;span style="color: rgb(0,0,255)"&gt;protected&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; CheckDisposed()
        {
            &lt;span style="color: rgb(0,0,255)"&gt;if&lt;/span&gt; (&lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.IsDisposed)
            {
                &lt;span style="color: rgb(0,0,255)"&gt;throw&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;new&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;ObjectDisposedException&lt;/span&gt;(&lt;span style="color: rgb(163,21,21)"&gt;&amp;quot;DataContextWrapper&amp;quot;&lt;/span&gt;);
            }
        }

        &lt;span style="color: rgb(0,0,255)"&gt;protected&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;virtual&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; Dispose(&lt;span style="color: rgb(0,0,255)"&gt;bool&lt;/span&gt; disposing)
        {
            &lt;span style="color: rgb(0,0,255)"&gt;if&lt;/span&gt; (!&lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.IsDisposed &amp;amp;&amp;amp; disposing)
            {
                &lt;span style="color: rgb(0,0,255)"&gt;if&lt;/span&gt; (&lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.DataContext != &lt;span style="color: rgb(0,0,255)"&gt;null&lt;/span&gt;)
                {
                    &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.DataContext.Dispose();

                    &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.IsDisposed = &lt;span style="color: rgb(0,0,255)"&gt;true&lt;/span&gt;;
                }
            }
        }

        &lt;span style="color: rgb(0,0,255)"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; Dispose()
        {
            &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.Dispose(&lt;span style="color: rgb(0,0,255)"&gt;true&lt;/span&gt;);

            &lt;span style="color: rgb(0,128,0)"&gt;// Suppress finalization of this disposed instance.
&lt;/span&gt;            &lt;span style="color: rgb(43,145,175)"&gt;GC&lt;/span&gt;.SuppressFinalize(&lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;);
        }

        ~DataContextWrapper()
        {
            Dispose(&lt;span style="color: rgb(0,0,255)"&gt;false&lt;/span&gt;);
        }

&lt;span style="color: rgb(0,0,255)"&gt;        #endregion
&lt;/span&gt;    }
}&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;h1&gt;Example&lt;/h1&gt;

&lt;p&gt;So how are these intended to be used?&amp;#160; Here's an example DataContextWrapper implementation:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre class="code"&gt;&lt;span style="color: rgb(0,0,255)"&gt;using&lt;/span&gt; System;
&lt;span style="color: rgb(0,0,255)"&gt;using&lt;/span&gt; System.IO;
&lt;span style="color: rgb(0,0,255)"&gt;using&lt;/span&gt; System.Linq;
&lt;span style="color: rgb(0,0,255)"&gt;using&lt;/span&gt; Northwind;
&lt;span style="color: rgb(0,0,255)"&gt;using&lt;/span&gt; Thuban.Data.Linq;

&lt;span style="color: rgb(0,0,255)"&gt;namespace&lt;/span&gt; Sample
{
    &lt;span style="color: rgb(0,0,255)"&gt;sealed&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;class&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;NorthwindWrapper&lt;/span&gt;: &lt;span style="color: rgb(43,145,175)"&gt;DataContextWrapper
&lt;/span&gt;    {
        &lt;span style="color: rgb(0,0,255)"&gt;public&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;TableView&lt;/span&gt;&amp;lt;&lt;span style="color: rgb(43,145,175)"&gt;Customer&lt;/span&gt;&amp;gt; Customers;

        &lt;span style="color: rgb(0,0,255)"&gt;public&lt;/span&gt; NorthwindWrapper()
            : &lt;span style="color: rgb(0,0,255)"&gt;base&lt;/span&gt;(&lt;span style="color: rgb(0,0,255)"&gt;new&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;NorthwindDataContext&lt;/span&gt;())
        {
        }

        &lt;span style="color: rgb(0,0,255)"&gt;public&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;TextWriter&lt;/span&gt; Log
        {
            &lt;span style="color: rgb(0,0,255)"&gt;get
&lt;/span&gt;            {
                &lt;span style="color: rgb(0,0,255)"&gt;return&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.DataContext.Log;
            }

            &lt;span style="color: rgb(0,0,255)"&gt;set
&lt;/span&gt;            {
                &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.DataContext.Log = &lt;span style="color: rgb(0,0,255)"&gt;value&lt;/span&gt;;
            }
        }

        &lt;span style="color: rgb(0,0,255)"&gt;protected&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;override&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;IQueryable&lt;/span&gt; GetQuery(&lt;span style="color: rgb(43,145,175)"&gt;Type&lt;/span&gt; entityType)
        {
            &lt;span style="color: rgb(0,0,255)"&gt;if&lt;/span&gt; (entityType == &lt;span style="color: rgb(0,0,255)"&gt;typeof&lt;/span&gt;(&lt;span style="color: rgb(43,145,175)"&gt;Customer&lt;/span&gt;))
            {
                &lt;span style="color: rgb(0,0,255)"&gt;return&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.CreateTableView&amp;lt;&lt;span style="color: rgb(43,145,175)"&gt;Customer&lt;/span&gt;&amp;gt;(c =&amp;gt; c.City == &lt;span style="color: rgb(163,21,21)"&gt;&amp;quot;London&amp;quot;&lt;/span&gt;);
            }
            &lt;span style="color: rgb(0,0,255)"&gt;else
&lt;/span&gt;            {
                &lt;span style="color: rgb(0,0,255)"&gt;return&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;null&lt;/span&gt;;
            }
        }
    }
}&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;Like the familiar DataContext, you subclass it and add public fields to represent the tables, which are populated during initialization.&amp;#160; The DataContextWrapper has only one constructor, which takes the DataContext instance to wrap, and so we forward our default constructor to that.&amp;#160; We add a Log property, since this is just a sample, but the most important item is the (required) implementation of GetQuery.&lt;/p&gt;

&lt;p&gt;GetQuery accepts the entity type that is being requested, and returns the IQueryable (ie, the TableView) that is appropriate.&amp;#160; The interaction here's a bit rough, so I may change it at some point, but it does that it's supposed to for now.&amp;#160; Maybe I'll just switch it to use the dictionary directly.&amp;#160; Remember -- this is just a quick sketch of &lt;em&gt;one&lt;/em&gt; approach.&lt;/p&gt;

&lt;p&gt;As you can see in the following, you use it as you would use DataContext normally:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre class="code"&gt;&lt;span style="color: rgb(0,0,255)"&gt;using&lt;/span&gt; System;
&lt;span style="color: rgb(0,0,255)"&gt;using&lt;/span&gt; System.Collections.Generic;
&lt;span style="color: rgb(0,0,255)"&gt;using&lt;/span&gt; System.Linq;
&lt;span style="color: rgb(0,0,255)"&gt;using&lt;/span&gt; System.Text;

&lt;span style="color: rgb(0,0,255)"&gt;namespace&lt;/span&gt; Sample
{
    &lt;span style="color: rgb(0,0,255)"&gt;class&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;Program
&lt;/span&gt;    {
        &lt;span style="color: rgb(0,0,255)"&gt;static&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; Main(&lt;span style="color: rgb(0,0,255)"&gt;string&lt;/span&gt;[] args)
        {
            &lt;span style="color: rgb(0,0,255)"&gt;using&lt;/span&gt; (&lt;span style="color: rgb(0,0,255)"&gt;var&lt;/span&gt; db = &lt;span style="color: rgb(0,0,255)"&gt;new&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;NorthwindWrapper&lt;/span&gt;() { Log = &lt;span style="color: rgb(43,145,175)"&gt;Console&lt;/span&gt;.Out })
            {

                &lt;span style="color: rgb(0,0,255)"&gt;var&lt;/span&gt; q = &lt;span style="color: rgb(0,0,255)"&gt;from&lt;/span&gt; c &lt;span style="color: rgb(0,0,255)"&gt;in&lt;/span&gt; db.Customers
                        &lt;span style="color: rgb(0,0,255)"&gt;where&lt;/span&gt; c.ContactName.StartsWith(&lt;span style="color: rgb(163,21,21)"&gt;&amp;quot;B&amp;quot;&lt;/span&gt;)
                        &lt;span style="color: rgb(0,0,255)"&gt;select&lt;/span&gt; c;

                &lt;span style="color: rgb(0,0,255)"&gt;foreach&lt;/span&gt; (&lt;span style="color: rgb(0,0,255)"&gt;var&lt;/span&gt; item &lt;span style="color: rgb(0,0,255)"&gt;in&lt;/span&gt; q)
                {
                    &lt;span style="color: rgb(43,145,175)"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color: rgb(163,21,21)"&gt;&amp;quot;Name = {0}; City = {1}&amp;quot;&lt;/span&gt;, item.ContactName, item.City);
                }
            }

            &lt;span style="color: rgb(43,145,175)"&gt;Console&lt;/span&gt;.ReadKey(&lt;span style="color: rgb(0,0,255)"&gt;true&lt;/span&gt;);
        }
    }
}&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;And it will produce the following output:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre class="code"&gt;SELECT [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName], [t0].[ContactTitle],
       [t0].[Address], [t0].[City], [t0].[Region], [t0].[PostalCode], [t0].[Country],
       [t0].[Phone], [t0].[Fax] 
FROM [dbo].[Customers] AS [t0] 
WHERE ([t0].[ContactName] LIKE @p0) &lt;font color="#ff0000"&gt;AND ([t0].[City] = @p1)&lt;/font&gt;
-- @p0: Input NVarChar (Size = 2; Prec = 0; Scale = 0) [B%] 
-- @p1: Input NVarChar (Size = 6; Prec = 0; Scale = 0) [London] 
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.21022.7&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;As you can see, the restriction on City was added automatically.&lt;/p&gt;

&lt;h1&gt;Future Considerations&lt;/h1&gt;

&lt;p&gt;This is not the approach that would solve the must-not-be-able-to-access-information-even-through-reflection approach.&amp;#160; Reflection is powerful -- if you wanted to, you could access the internals of the change tracker.&amp;#160; For those cases -- where information is secured by its absence, rather than secured by hiding it in the closet -- I'd suggest enforcing it at the server.&amp;#160; Otherwise, of course, what is to prevent someone from using ADO.NET?&lt;/p&gt;

&lt;p&gt;Also, don't fall into the trap of thinking there's only one possible data context for a given database.&amp;#160; Create multiple ones when it makes sense:&amp;#160; an administrative context with everything, a narrowly-focused context for plug-in modules, and so forth.&amp;#160; The context isn't so much the database made manifest as it is just the limit of LINQ to SQL's view.&amp;#160; Anything outside that view just isn't known about -- it can't be queried, and it can't be meddled with.&amp;#160; Provided you encapsulate your data context, you can prevent gratuitous GetTable calls on newly-mapped types.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=6200202" width="1" height="1"&gt;</content><author><name>kfarmer@microsoft.com</name><uri>http://blogs.msdn.com/members/kfarmer%40microsoft.com.aspx</uri></author></entry><entry><title>LINQ and 3-Tier Dogma</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/kfarmer/archive/2007/11/06/linq-and-3-tier-dogma.aspx" /><id>http://blogs.msdn.com/kfarmer/archive/2007/11/06/linq-and-3-tier-dogma.aspx</id><published>2007-11-07T03:15:00Z</published><updated>2007-11-07T03:15:00Z</updated><content type="html">&lt;P&gt;One of the most frequent questions we've received about LINQ to SQL deals with fitting it into the classic three-tiered scenario.&amp;nbsp; That is:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;Presentation --- Logic --- Data&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;I know someone somewhere is going to accuse me of heresy for what I'm about to state, but it's something I've wanted to get off my chest for a couple years, since I first encountered LINQ to SQL, and started to realize what it meant...&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;The 3-Tier Model is just a pattern.&lt;/STRONG&gt;&amp;nbsp; &lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;And, like all patterns, &lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;It is meant to serve our needs, not the other way around.&lt;/STRONG&gt;&amp;nbsp; &lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Don't get hung up on academic concerns such as how many tiers you have in your system.&amp;nbsp; You'll just waste the time you could spend doing things you actually need to do.&amp;nbsp; Such as watching Avatar or playing Warcraft.&lt;/P&gt;
&lt;P&gt;There, I said it.&lt;/P&gt;
&lt;P&gt;And saying that, I think LINQ to SQL fits perfectly well into the 3-Tier Model.&lt;/P&gt;
&lt;P&gt;The spirit of the 3TM is that, in keeping your layers seperate, you achieve the ability to swap out data access, business logic, or presentation interfaces without disturbing the other two (or the functionality that depends on them).&amp;nbsp; This, without dispute, is a useful thing.&amp;nbsp; But there are various levels of purity that people seem to think apply:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;contractual purity (there is a set of well-known interfaces between the tiers)&lt;/LI&gt;
&lt;LI&gt;binary purity (the types are completely seperate in each tier, *and* there is a contract between each)&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Frequently, I've seen people get hung up on the idea of binary purity.&amp;nbsp; I'll say it:&amp;nbsp; I don't think it honestly matters.&amp;nbsp; &lt;EM&gt;Within the scope of a single project&lt;/EM&gt; (and I'll submit that a web service and a web client are in fact two different projects), there is no gain in creating parallel sets of objects just for the sake of doing so.&amp;nbsp; That is, there is no longer a compellingly good&amp;nbsp;reason, and in fact I now consider it questionable design, in having "ProductDataObject" and "ProductLogicalObject" in the same project,&amp;nbsp;when the shapes of the two&amp;nbsp;are the same.&amp;nbsp; You'll spend all your time copying property values back and forth, your references won't track well,&amp;nbsp;and you'll forgo any change- or identity- tracking that the data layer happens to give you.&amp;nbsp; &lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;EM&gt;Don't underestimate the value of&amp;nbsp;tracking features in a data layer.&lt;/EM&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;So, let's just ditch the idea of binary purity for purity's sake; it's only real use is when transmitting data packets to foreign systems.&amp;nbsp; Instead, let's talk about contractual purity.&lt;/P&gt;
&lt;P&gt;Contractual purity is great.&amp;nbsp; I like it a lot, and I think this is where the true heart of n-tier modelling is to be found.&amp;nbsp; The only question is how you define your contracts.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;EM&gt;Really, that's up to you.&lt;/EM&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Consider LINQ to SQL for a moment.&amp;nbsp; LINQ to SQL was designed for those situations where the schema of your database matches the shape of data in what we'll loosely call your "logic" or "business"&amp;nbsp;layer.&amp;nbsp; (Loosely, because there can be many layers to this, or none at all for a dumb reporting app.)&amp;nbsp; That is:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;Presentation --- Logic --- Data&lt;BR&gt;A --- B --- B&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;LINQ to SQL presents us with this:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;A ---&amp;nbsp;B&amp;nbsp;=== B&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;LINQ to SQL's already encapsulated your database access code (that is why it was written); it's all contained in System.Data.Linq.dll and your mapping metadata.&amp;nbsp; It also already talks in terms of your logical model, and that's fine because we already said that was what LINQ to SQL was designed to do.&lt;/P&gt;
&lt;P&gt;That leaves us with the question of what we use for presentation.&amp;nbsp; Again, that's entirely up to you.&amp;nbsp; If your project is such that is doesn't require formal contracts, and if the data being displayed has the same shape as what's available, why *not* use your logical model directly?&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;ui.DataSource = db.Customers;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;B&amp;nbsp;=== B === B&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;More often, of course, you'll be displaying composite data, and the shape of that will be somewhat different than your logical data.&amp;nbsp; Fine.&amp;nbsp; We can do that:&amp;nbsp; project into anonymous types (eg, if you don't need to access the properties directly -- if your UI does reflection), or project into a contractually-defined type, and return that:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;ui.DataSource = db.Customers.Select(c =&amp;gt; new { c.LastName, c.FirstName });&lt;BR&gt;ui.DataSource = db.Customers.Select(c =&amp;gt; new CustomerName { Last = c.LastName, First = c.First });&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;A&amp;nbsp;--- B === B&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Ah, you say.&amp;nbsp; You feel its sinful to even expose the tables on your data context.&amp;nbsp; Okay, fine.&amp;nbsp; Remove them.&amp;nbsp; In fact, &lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;EM&gt;Encapsulate your data context.&lt;/EM&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;That is,&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;public class MyLogicLayer: IDisposable // MyLogicLayer is IDisposable because MyDataContext is IDisposable&lt;BR&gt;{&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;// We retain an instance of the context.&amp;nbsp; It's not static, because contexts are designed to be short-lived.&lt;BR&gt;MyDataContext db;&lt;/P&gt;
&lt;P&gt;// We want to update data, right?&lt;BR&gt;public void SubmitChanges()&lt;BR&gt;{&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;db.SubmitChanges();&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;}&lt;/P&gt;
&lt;P&gt;// I prefer IQueryable, because I want my filtering and sorting to happen at the server, not the client.&lt;BR&gt;// That is, I want to write:&amp;nbsp; logicLayer.GetCustomersInWa().OrderBy(c =&amp;gt; c.Age)&lt;BR&gt;public IQueryable&amp;lt;Customer&amp;gt; GetCustomersInWA()&lt;BR&gt;{&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;return db.Customers.Where(c =&amp;gt; c.State == "WA").OrderBy(c =&amp;gt; c.LastName).ThenBy(c =&amp;gt; c.FirstName);&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;}&lt;/P&gt;
&lt;P&gt;// TVFs are a much more useful alternative to sprocs.&amp;nbsp; In particular, they're composable.&lt;BR&gt;public IQueryable&amp;lt;Customer&amp;gt; TVF_GetCustomersInWA()&lt;BR&gt;{&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;return db.GetCustomersInStateTVF("WA").OrderBy(c =&amp;gt; c.LastName).ThenBy(c =&amp;gt; c.FirstName);&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;}&lt;/P&gt;
&lt;P&gt;// Of course, getting a single customer is useful&lt;BR&gt;public Customer GetCustomer(int id)&lt;BR&gt;{&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;return db.Customers.Where(c =&amp;gt; c.CustomerId == id);&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;}&lt;/P&gt;
&lt;P&gt;// Maybe some admin doesn't want you to know about the customer's birthdate.&amp;nbsp; So make a trimmed-down ICustomer,&lt;BR&gt;// and return based on that interface.&lt;BR&gt;public ICustomer GetCustomer(int id)&lt;BR&gt;{&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;// where the interface is sufficient protection&lt;BR&gt;return db.Customers.Where(c =&amp;gt; c.CustomerId == id);&lt;/P&gt;
&lt;P&gt;or&lt;/P&gt;
&lt;P&gt;// where CustomerWithoutBirthdate implements ICustomer, and whose properties defer to the contained Customer&lt;BR&gt;return db.Customer.Where(c =&amp;gt; c.CustomerID == id).Select(c =&amp;gt; new CustomerWithoutBirthdate(c)); &lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;}&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;}&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Which, interestingly,&amp;nbsp;looks like:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;A&amp;nbsp;=== [ A --- B ]&amp;nbsp;=== B&lt;BR&gt;B&amp;nbsp;=== [ B&amp;nbsp;=== B ]&amp;nbsp;=== B&lt;BR&gt;B'&amp;nbsp;=== [&amp;nbsp;B'&amp;nbsp;=== B ]&amp;nbsp;=== B&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;.. depending on which method you call.&amp;nbsp; In other words,&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;EM&gt;The encapsulation of the data context is the creation of the logical layer.&lt;/EM&gt;&amp;nbsp;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;I'm sure that in the upcoming years, there will be plenty of other ways people will find to adapt the traditional architectures to new innovations, and I'm certain there will be further innovations that make what I just proprosed easier to swallow.&amp;nbsp; And that's what makes programming interesting.&amp;nbsp; If we have indeed solved all the problems and programming is perfect forever, where's the fun in that?&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5948713" width="1" height="1"&gt;</content><author><name>kfarmer@microsoft.com</name><uri>http://blogs.msdn.com/members/kfarmer%40microsoft.com.aspx</uri></author></entry><entry><title>PS CodePlex</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/kfarmer/archive/2007/10/12/ps-codeplex.aspx" /><id>http://blogs.msdn.com/kfarmer/archive/2007/10/12/ps-codeplex.aspx</id><published>2007-10-12T11:02:00Z</published><updated>2007-10-12T11:02:00Z</updated><content type="html">&lt;P&gt;For some reason I decided to write some PowerShell functions to manage checking out projects from CodePlex, and updating them in batch.&amp;nbsp; It makes use of the CodePlex Client (cpc), which allows anonymous access to CodePlex's TFS repository.&lt;/P&gt;
&lt;P&gt;They're fairly primitive, but seem to do the job.&amp;nbsp; You'll need to have cpc in your path, and you'll notice I've defined a drive 'CodePlex' at the repository root.&amp;nbsp; There's also a $CodePlexDirectory variable I'm setting in my profile which contains the path to where CodePlex: is rooted.&lt;/P&gt;
&lt;P&gt;What I should do is install them on one of my servers at home and set update-codeplex on a timer to just automatically retrieve the latest changes.&amp;nbsp; Maybe even do a build.&lt;/P&gt;
&lt;P&gt;function view-codeplex&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; param([string] $project = $(throw "Provide a project name"))&amp;nbsp; &lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $destination = 'http://www.codeplex.com/' + $project&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; start $destination&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;function get-codeplex&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; param([string] $project = $(throw "Provide a project name"))&amp;nbsp; &lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;$destination = (Join-Path $CodePlexDirectory $project)&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; cpc checkout $project $destination&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; push-location $destination&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;cpc info&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; pop-location&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;function update-codeplex&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;param([string] $project)&amp;nbsp; &lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;$list = , $project&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($project -eq "")&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; $list = (get-childitem 'CodePlex:\\' | foreach-object { $_.Name })&lt;BR&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;foreach ($item in $list)&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; push-location (Join-Path 'CodePlex:' $item)&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cpc info&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cpc update&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pop-location&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;BR&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5418187" width="1" height="1"&gt;</content><author><name>kfarmer@microsoft.com</name><uri>http://blogs.msdn.com/members/kfarmer%40microsoft.com.aspx</uri></author></entry><entry><title>Quantum Computer Demonstration</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/kfarmer/archive/2007/02/12/quantum-computer-demonstration.aspx" /><id>http://blogs.msdn.com/kfarmer/archive/2007/02/12/quantum-computer-demonstration.aspx</id><published>2007-02-13T10:53:00Z</published><updated>2007-02-13T10:53:00Z</updated><content type="html">&lt;P&gt;Tomorrow, &lt;A class="" href="http://www.dwavesys.com/" mce_href="http://www.dwavesys.com"&gt;D-Wave Systems&lt;/A&gt;&amp;nbsp;with either become a laughing stock, or the state of computing will arguably have advanced by 20 years.&lt;/P&gt;
&lt;P&gt;They plan to demonstrate a 16-qubit computer running two commercial apps simultaneously, and repeat the feat on Thursday.&lt;/P&gt;
&lt;P&gt;Now if they can figure out how to get it to simultaneously compute every possible bug-free application, they could save us a lot of effort.&lt;/P&gt;
&lt;P&gt;You can sign up for premium content on their website.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1667497" width="1" height="1"&gt;</content><author><name>kfarmer@microsoft.com</name><uri>http://blogs.msdn.com/members/kfarmer%40microsoft.com.aspx</uri></author></entry><entry><title>Multi-threaded Linq</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/kfarmer/archive/2006/04/01/566466.aspx" /><link rel="enclosure" type="application/x-zip-compressed" length="5159" href="http://blogs.msdn.com/kfarmer/attachment/566466.ashx" /><id>http://blogs.msdn.com/kfarmer/archive/2006/04/01/566466.aspx</id><published>2006-04-01T12:32:00Z</published><updated>2006-04-01T12:32:00Z</updated><content type="html">&lt;P&gt;I decided to play around with the idea of a multi-threaded Select extension.&amp;nbsp; This could be useful, for example, if you're creating a system that farms out work to various web services and have a limited number of connections to use.&lt;/P&gt;
&lt;P&gt;Attached should be the results of my excursion.&lt;/P&gt;
&lt;P&gt;While I've created multi-threaded applications before, I hadn't yet created one where it continuously tried to ensure that the maximum number of threads possible were used, while also ensuring that the sequence of results matched the sequence of inputs.&amp;nbsp; The basic algorithm I came up with is fairly straightforward:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Fetch the enumerator of the input.&lt;/LI&gt;
&lt;LI&gt;Set lastMoveNextWasTrue to true, as an initial value.&lt;/LI&gt;
&lt;LI&gt;While lastMoveNextWasTrue:&lt;/LI&gt;
&lt;OL&gt;
&lt;LI&gt;While there are spare threads and buffer space:&lt;/LI&gt;
&lt;OL&gt;
&lt;LI&gt;Set lastMoveNextWasTrue to enumerator.MoveNext()&lt;/LI&gt;
&lt;LI&gt;If lastMoveNextWasTrue, then create a new BackgroundWorker and results object, and store them off.&amp;nbsp; Build the arguments, and run the worker.&amp;nbsp; Else break.&lt;/LI&gt;&lt;/OL&gt;
&lt;LI&gt;Wait for at least one worker to complete.&lt;/LI&gt;
&lt;LI&gt;While true:&lt;/LI&gt;
&lt;OL&gt;
&lt;LI&gt;Remove completed workers.&lt;/LI&gt;
&lt;LI&gt;While the head of the buffer contains results from completed workers, yield them.&lt;/LI&gt;
&lt;LI&gt;If lastMoveNextWasTrue was false (no more items to consume) and there are still workers running, continue at (3).&amp;nbsp; Else break.&lt;/LI&gt;&lt;/OL&gt;&lt;/OL&gt;&lt;/OL&gt;
&lt;P&gt;A similar logic can be had for the ForEach case (takes an Action&amp;lt;T&amp;gt;).&lt;/P&gt;
&lt;P&gt;The results show that this sort of approach is worthwhile when the processing is IO-bound (simulated here with Thread.Sleep(1)):&amp;nbsp; with 5 threads and 3 maximum pending results, I get roughly 2x performance.&amp;nbsp; If instead I'm calculating factorials -- CPU-bound -- the overhead involved makes this just a little slower.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=566466" width="1" height="1"&gt;</content><author><name>kfarmer@microsoft.com</name><uri>http://blogs.msdn.com/members/kfarmer%40microsoft.com.aspx</uri></author></entry><entry><title>Indexed Linq</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/kfarmer/archive/2006/03/15/552615.aspx" /><id>http://blogs.msdn.com/kfarmer/archive/2006/03/15/552615.aspx</id><published>2006-03-16T09:35:00Z</published><updated>2006-03-16T09:35:00Z</updated><content type="html">&lt;P&gt;&lt;A href="http://weblogs.asp.net/brianbec/archive/2006/03/15/440293.aspx"&gt;Brian Beckman&lt;/A&gt; shows off a simple hash join in &lt;a href="http://msdn.microsoft.com/netframework/future/linq/default.aspx"&gt;LINQ&lt;/a&gt;, using VB9.&amp;nbsp; The performace boosts reinforce some work my partner and I did, experimenting with load-time generated indexes over collections.&lt;/P&gt;
&lt;P&gt;There was a significant hit incurred when creating the index, but it was assumed that you wouldn't bother unless it actually did any good.&lt;/P&gt;
&lt;P&gt;The code below is somewhat naive, but shows one approach.&amp;nbsp; In this case, the index tracks several different features of a number, even/odd, positive/negative, and the values modulo 10 and modulo 3.&amp;nbsp; The query is then over the index partitions, rather than the raw collection, and returns a new index containing just the partitions that matched.&amp;nbsp; Enumerating over an index yields the indexed items.&lt;/P&gt;
&lt;P&gt;On my system, I get times similar to these.&amp;nbsp; The qa* are queries over a List&amp;lt;double&amp;gt;, while qb* are queries over an Indexable&amp;lt;double, NumberIndex&amp;gt;.&amp;nbsp; The total range of doubles went from -1e7 to +1e7.&lt;/P&gt;&lt;PRE&gt;Time to create index = 21943ms
qa1: Count = 1000000; Time = 2131ms
qa2: Count = 9999999; Time = 1470ms
qa3: Count = 10000000; Time = 2396ms
qa4: Count = 333333; Time = 1965ms
qb1: Count = 1000000; Time = 87ms
qb2: Count = 9999999; Time = 616ms
qb3: Count = 10000000; Time = 812ms
qb4: Count = 333333; Time = 22ms
&lt;/PRE&gt;
&lt;P&gt;Code follows...&lt;/P&gt;&lt;PRE&gt;using System;
using System.Collections.Generic;
using System.Text;
using System.Query;
using System.Xml.XLinq;
using System.Data.DLinq;

namespace IndexLinq
{
    public class Indexable&amp;lt;TItem, TKey&amp;gt; : IEnumerable&amp;lt;TItem&amp;gt;
    {
        internal Dictionary&amp;lt;TKey, List&amp;lt;TItem&amp;gt;&amp;gt; _index = new Dictionary&amp;lt;TKey, List&amp;lt;TItem&amp;gt;&amp;gt;();
        internal Func&amp;lt;TItem, TKey&amp;gt; _indexer;
        private int? _capacity = null;

        public Indexable(Func&amp;lt;TItem, TKey&amp;gt; indexer)
        {
            this._indexer = indexer;
        }

        public void AddRange(IEnumerable&amp;lt;TItem&amp;gt; source)
        {
            if (this._indexer != null)
            {
                Refresh(source);
            }
        }

        public void AddRange(IEnumerable&amp;lt;TItem&amp;gt; source, int capacity)
        {
            this._capacity = capacity;

            AddRange(source);
        }

        public void AddRange(IList&amp;lt;TItem&amp;gt; source)
        {
            AddRange(source, source.Count / 10);
        }

        public void Clear()
        {
            this._index.Clear();
        }

        private void Refresh(IEnumerable&amp;lt;TItem&amp;gt; items)
        {
            if (items == null || _index == null)
            {
                throw new InvalidOperationException("Unable to refresh when indexable does not have both a source and an indexer defined.");
            }

            foreach (TItem item in items)
            {
                TKey key = _indexer(item);

                if (!_index.ContainsKey(key))
                {
                    if (this._capacity.HasValue)
                    {
                        _index.Add(key, new List&amp;lt;TItem&amp;gt;(this._capacity.Value));
                    }
                    else
                    {
                        _index.Add(key, new List&amp;lt;TItem&amp;gt;());
                    }

                    Console.WriteLine("Added new key: {0}", key);
                }

                _index[key].Add(item);
            }
        }

        #region IEnumerable&amp;lt;TItem&amp;gt; Members

        public IEnumerator&amp;lt;TItem&amp;gt; GetEnumerator()
        {
            foreach (List&amp;lt;TItem&amp;gt; list in _index.Values)
            {
                foreach (TItem item in list)
                {
                    yield return item;
                }
            }
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }

        #endregion
    }
}
&lt;/PRE&gt;
&lt;HR width="50%"&gt;
&lt;PRE&gt;using System;
using System.Collections.Generic;
using System.Text;

namespace IndexLinq
{
    public static class IndexLinqExtensions
    {
        public static Indexable&amp;lt;TItem, TKey&amp;gt; Where&amp;lt;TItem, TKey&amp;gt;(this Indexable&amp;lt;TItem, TKey&amp;gt; indexable, Predicate&amp;lt;TKey&amp;gt; predicate)
        {
            Indexable&amp;lt;TItem, TKey&amp;gt; result = new Indexable&amp;lt;TItem, TKey&amp;gt;(indexable._indexer);

            foreach (TKey key in indexable._index.Keys)
            {
                if (predicate(key))
                {
                    result._index.Add(key, indexable._index[key]);
                }
            }

            return result;
        }
    }
}
&lt;/PRE&gt;
&lt;HR width="50%"&gt;
&lt;PRE&gt;using System;
using System.Collections.Generic;
using System.Text;
using System.Query;
using System.Xml.XLinq;
using System.Data.DLinq;
using IndexLinq;
using System.Diagnostics;

namespace IndexLinqTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var numbers = new List&amp;lt;double&amp;gt;(Numbers(-1e7, 1e7));

            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Reset();
            stopwatch.Start();

            var indexed = new Indexable&lt;DOUBLE, NumberIndex&gt;(new Func&lt;DOUBLE, NumberIndex&gt;(Indexer));
            indexed.AddRange(numbers);

            stopwatch.Stop();

            Console.WriteLine("Time to create index = {0}ms", stopwatch.ElapsedMilliseconds);

            // non-indexed

            var qa1 = from i in numbers where i % 10 == 1 select i; 
            var qa2 = from i in numbers where i &amp;gt; 0 select i;
            var qa3 = from i in numbers where i % 2 == 0 select i;
            var qa4 = from i in numbers where i % 10 == 1 &amp;amp;&amp;amp; i % 3 == 0 select i;

            // indexed

            var qb1 = from i in indexed where i.Mod10 == 1 select i; 
            var qb2 = from i in indexed where i.IsPositive == true select i;            
            var qb3 = from i in indexed where i.IsEven == true select i;
            var qb4 = from i in indexed where i.Mod10 == 1 &amp;amp;&amp;amp; i.Mod3 == 0 select i;

            var queries = new[] {
                new object[]{ qa1, "qa1" },
                new object[]{ qa2, "qa2" },
                new object[]{ qa3, "qa3" },
                new object[]{ qa4, "qa4" },
                new object[]{ qb1, "qb1" },
                new object[]{ qb2, "qb2" },
                new object[]{ qb3, "qb3" },
                new object[]{ qb4, "qb4" }
            };

            int count;
            
            foreach (object[] query in queries)
            {
                count = 0;

                stopwatch.Reset();
                stopwatch.Start();

                foreach (var i in query[0] as IEnumerable&amp;lt;double&amp;gt;)
                {
                    count++;
                }

                stopwatch.Stop();
                
                Console.WriteLine("{0}: Count = {1}; Time = {2}ms", 
                    query[1], 
                    count, 
                    stopwatch.ElapsedMilliseconds
                    );
            }

            Console.ReadKey(true);
        }

        public struct NumberIndex
        {
            public bool IsEven;
            public bool IsPositive;
            public double Mod10;
            public double Mod3;

            public override bool Equals(object obj)
            {
                if (!(obj is NumberIndex)) return false;

                NumberIndex numberIndex = (NumberIndex) obj;

                return this.IsEven == numberIndex.IsEven
                    &amp;amp;&amp;amp; this.IsPositive == numberIndex.IsPositive
                    &amp;amp;&amp;amp; this.Mod10 == numberIndex.Mod10
                    &amp;amp;&amp;amp; this.Mod3 == numberIndex.Mod3;
            }

            public override int GetHashCode()
            {
                return (int) (this.Mod10 * 1000 + (this.Mod3 * 100) + (this.IsEven ? 10 : 0) + (this.IsPositive ? 1 : 0));
            }

            public override string ToString()
            {
                return String.Format(@"[Mod10 = {0}; Mod3 = {3}; IsEven = {1}; IsPositive = {2}]", this.Mod10, this.IsEven, this.IsPositive, this.Mod3);
            }
        }

        static NumberIndex Indexer(double i)
        {
            NumberIndex result = new NumberIndex();

            result.IsEven = (i % 2 == 0);
            result.IsPositive = (i &amp;gt; 0);
            result.Mod10 = (i % 10);
            result.Mod3 = (i % 3);

            return result;
        }

        static IEnumerable&amp;lt;double&amp;gt; Numbers(double start, double end)
        {
            if (start &amp;gt; end)
            {
                double x = end;
                end = start;
                start = x;
            }

            for (double i = start; i &amp;lt; end; i++)
            {
                yield return i;
            }
        }
    }
}
&lt;/PRE&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=552615" width="1" height="1"&gt;</content><author><name>kfarmer@microsoft.com</name><uri>http://blogs.msdn.com/members/kfarmer%40microsoft.com.aspx</uri></author></entry><entry><title>ChemLinq</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/kfarmer/archive/2006/03/15/551780.aspx" /><id>http://blogs.msdn.com/kfarmer/archive/2006/03/15/551780.aspx</id><published>2006-03-15T10:31:00Z</published><updated>2006-03-15T10:31:00Z</updated><content type="html">&lt;P&gt;A customer posed a good question to me the other day:&amp;nbsp; outside of relational databases, what good is &lt;a href="http://msdn.microsoft.com/netframework/future/linq/default.aspx"&gt;LINQ&lt;/a&gt;?&amp;nbsp; As an example, he suggested a chemistry drawing application.&lt;/P&gt;
&lt;P&gt;I couldn't help him directly on the GUI aspects, but I decided to figure out, given a graph of atoms and bonds representing a molecule, how to find patterns in the structure.&amp;nbsp; In the specific example, I decided to locate hydroxyl ions (-OH).&lt;/P&gt;
&lt;P&gt;The query boils down to this:&amp;nbsp; find the hydrogen atoms with a single bond, which goes to an oxygen atom, which has only one other bond not going to the original hydrogen.&lt;/P&gt;
&lt;P&gt;The following is a working example, and compiles against the CTP release of &lt;a href="http://msdn.microsoft.com/netframework/future/linq/default.aspx"&gt;LINQ&lt;/a&gt;. Obviously, with some more thought put into the chemistry object model, the code could be simplified, and potentially more sophisticated queries executed.&amp;nbsp; One early (and as yet untested) speculation had me writing something like:&lt;/P&gt;&lt;PRE&gt;from atom in molecule.Atoms
where atom.Element == Element.Hydrogen
and atom.Bonds.Count == 1
from atom2 in atom.Bonds[0].FindAtom(a =&amp;gt; a != atom &amp;amp;&amp;amp; a.Element == Element.Oxygen)
where atom2.FindBonds(b =&amp;gt; b != atom.Bonds[0]).Count == 1
select atom2.FindBonds(b =&amp;gt; b != atom.Bonds[0])[0].FindAtom(a =&amp;gt; a != atom2)
&lt;/PRE&gt;
&lt;P&gt;Code follows:&lt;/P&gt;&lt;PRE&gt;using System;
using System.Collections.Generic;
using System.Text;
using System.Query;
using System.Xml.XLinq;
using System.Data.DLinq;
using System.Collections.ObjectModel;

namespace ChemLinq
{
    class Program
    {
        enum Element
        {
            Hydrogen = 1,
            Oxygen = 8,
            Carbon = 12
        }

        class Atom
        {
            public Element Element;

            public Collection&amp;lt;Bond&amp;gt; Bonds;

            public Atom(Element element)
            {
                this.Element = element;
                Bonds = new Collection&amp;lt;Bond&amp;gt;();
            }
        }

        class Bond
        {
            public Collection&amp;lt;Atom&amp;gt; Atoms;

            public Bond(params Atom[] atoms)
            {
                Atoms = new Collection&amp;lt;Atom&amp;gt;(atoms);

                foreach (Atom a in atoms)
                {
                    a.Bonds.Add(this);
                }
            }
        }

        static void Main(string[] args)
        {
            // create Carbon Ring -- a MoleculeBuilder class would be useful here

            var c1 = new Atom(Element.Carbon);
            var c2 = new Atom(Element.Carbon);
            var c3 = new Atom(Element.Carbon);
            var c4 = new Atom(Element.Carbon);
            var c5 = new Atom(Element.Carbon);
            var c6 = new Atom(Element.Carbon);

            var bond12 = new Bond(c1, c2);
            var bond23 = new Bond(c2, c3);
            var bond34 = new Bond(c3, c4);
            var bond45 = new Bond(c4, c5);
            var bond56 = new Bond(c5, c6);
            var bond61 = new Bond(c6, c1);

            // create Hydroxyl ions

            var o1 = new Atom(Element.Oxygen);
            var o3 = new Atom(Element.Oxygen);
            var o5 = new Atom(Element.Oxygen);

            var h1 = new Atom(Element.Hydrogen);
            var h3 = new Atom(Element.Hydrogen);
            var h5 = new Atom(Element.Hydrogen);

            var bondOh1 = new Bond(o1, h1);
            var bondOh3 = new Bond(o3, h3);
            var bondOh5 = new Bond(o5, h5);

            // bond the ions to the ring

            var bond1 = new Bond(o1, c1);
            var bond3 = new Bond(o3, c3);
            var bond5 = new Bond(o5, c5);

            // bundle these into a molecule
            var molecule = new[] { c1, c2, c3, c4, c5, c6, o1, o3, o5, h1, h3, h5 };

            // query the structure to locate the hydroxyls

            // this could be cleaned up with some appropriate helper methods
            // on Atom and Bond

            var query = 
                from hAtom in molecule                          // search the molecule
                where hAtom.Element == Element.Hydrogen         // for hydrogen atoms
                &amp;amp;&amp;amp; hAtom.Bonds.Count == 1                       // with a single bond;
                    from hBond in hAtom.Bonds                   // search those bonds
                    where hBond.Atoms.Count == 2                // which have only 2 atoms
                        from oAtom in hBond.Atoms               // and find those where
                        where oAtom.Element == Element.Oxygen   // the other atom is oxygen
                        &amp;amp;&amp;amp; oAtom.Bonds.Count == 2               // and which has only 2 bonds;
                            from oBond in oAtom.Bonds           // then take the bond
                            where oBond.Atoms.Count == 2        // that go to only 1 other atom
                            &amp;amp;&amp;amp; !oBond.Atoms.Contains(hAtom)     // but not to the original hAtom
                            select oAtom;                       // and select that oxygen atom


            Console.WriteLine(query.Count()); // outputs 3

            Console.ReadKey(true);
        }
    }
}
&lt;/PRE&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=551780" width="1" height="1"&gt;</content><author><name>kfarmer@microsoft.com</name><uri>http://blogs.msdn.com/members/kfarmer%40microsoft.com.aspx</uri></author></entry></feed>