<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://weblogs.asp.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>Dixin's Blog</title><link>http://weblogs.asp.net/dixin/default.aspx</link><description>Dixin is a UI designer and knows a little bit about programming.</description><dc:language>en</dc:language><generator>CommunityServer 2007 SP1 (Build: 20510.895)</generator><item><title>My new car at Microsoft Building 35</title><link>http://weblogs.asp.net/dixin/archive/2011/06/05/my-new-car-at-microsoft-building-35.aspx</link><pubDate>Mon, 06 Jun 2011 05:04:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:7819738</guid><dc:creator>Dixin</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/dixin/rsscomments.aspx?PostID=7819738</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/dixin/commentapi.aspx?PostID=7819738</wfw:comment><comments>http://weblogs.asp.net/dixin/archive/2011/06/05/my-new-car-at-microsoft-building-35.aspx#comments</comments><description>&lt;p&gt;I am&amp;nbsp;so excited to have&amp;nbsp;it. These photos were taken when it is parked at Microsoft Building 35:&lt;/p&gt;  &lt;p&gt;&lt;img style="border-width: 0px; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="DSC_1174" border="0" alt="DSC_1174" src="http://weblogs.asp.net/blogs/dixin/DSC_1174_7C1D4F67.jpg" width="640" height="426" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_1174_7C1D4F67.jpg"&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="border-width: 0px; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="DSC_1167" border="0" alt="DSC_1167" src="http://weblogs.asp.net/blogs/dixin/DSC_1167_7AD8B688.jpg" width="640" height="426" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_1167_7AD8B688.jpg"&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="DSC_1172" border="0" alt="DSC_1172" src="http://weblogs.asp.net/blogs/dixin/DSC_1172_15A4DC95.jpg" width="640" height="426" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_1172_15A4DC95.jpg"&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="DSC_1656" border="0" alt="DSC_1656" src="http://weblogs.asp.net/blogs/dixin/DSC_1656_1F1D9B0B.jpg" width="640" height="426" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_1656_1F1D9B0B.jpg"&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="DSC_1658" border="0" alt="DSC_1658" src="http://weblogs.asp.net/blogs/dixin/DSC_1658_1DD9022C.jpg" width="640" height="426" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_1658_1DD9022C.jpg"&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="DSC_1676" border="0" alt="DSC_1676" src="http://weblogs.asp.net/blogs/dixin/DSC_1676_15E15FCA.jpg" width="640" height="426" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_1676_15E15FCA.jpg"&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="DSC_1680" border="0" alt="DSC_1680" src="http://weblogs.asp.net/blogs/dixin/DSC_1680_30AD85D6.jpg" width="640" height="426" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_1680_30AD85D6.jpg"&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="DSC_2471" border="0" alt="DSC_2471" src="http://weblogs.asp.net/blogs/dixin/DSC_2471_4CB0D365.jpg" width="640" height="426"&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="DSC_1704" border="0" alt="DSC_1704" src="http://weblogs.asp.net/blogs/dixin/DSC_1704_4F83F9B4.jpg" width="640" height="426" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_1704_4F83F9B4.jpg"&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="DSC_1677" border="0" alt="DSC_1677" src="http://weblogs.asp.net/blogs/dixin/DSC_1677_329AD4DF.jpg" width="640" height="426" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_1677_329AD4DF.jpg"&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="DSC_1697" border="0" alt="DSC_1697" src="http://weblogs.asp.net/blogs/dixin/DSC_1697_7DADCFA1.jpg" width="640" height="426" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_1697_7DADCFA1.jpg"&gt;&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=7819738" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/dixin/archive/tags/Microsoft+Redmond+Campus/default.aspx">Microsoft Redmond Campus</category></item><item><title>Understanding LINQ to SQL (11) Performance</title><link>http://weblogs.asp.net/dixin/archive/2011/01/31/understanding-linq-to-sql-11-performance.aspx</link><pubDate>Mon, 31 Jan 2011 21:00:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:7678430</guid><dc:creator>Dixin</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/dixin/rsscomments.aspx?PostID=7678430</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/dixin/commentapi.aspx?PostID=7678430</wfw:comment><comments>http://weblogs.asp.net/dixin/archive/2011/01/31/understanding-linq-to-sql-11-performance.aspx#comments</comments><description>&lt;P&gt;[&lt;A href="http://weblogs.asp.net/dixin/archive/2009/09/07/linq-via-csharp.aspx" target=_blank mce_href="http://weblogs.asp.net/dixin/archive/2009/09/07/linq-via-csharp.aspx"&gt;LINQ via C# series&lt;/A&gt;]&lt;/P&gt;
&lt;P&gt;LINQ to SQL has a lot of great features like&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;strong typing &lt;/LI&gt;
&lt;LI&gt;query compilation &lt;/LI&gt;
&lt;LI&gt;deferred execution &lt;/LI&gt;
&lt;LI&gt;declarative paradigm &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;etc., which are very productive. Of course, these cannot be free, and one price is the performance.&lt;/P&gt;
&lt;H1&gt;O/R mapping overhead&lt;/H1&gt;
&lt;P&gt;Because LINQ to SQL is based on O/R mapping, one obvious overhead is, data changing usually requires data retrieving:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;private static void &lt;/SPAN&gt;UpdateProductUnitPrice(&lt;SPAN style="COLOR: blue"&gt;int &lt;/SPAN&gt;id, &lt;SPAN style="COLOR: blue"&gt;decimal &lt;/SPAN&gt;unitPrice)
{
    &lt;SPAN style="COLOR: blue"&gt;using &lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;NorthwindDataContext &lt;/SPAN&gt;database = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;NorthwindDataContext&lt;/SPAN&gt;())
    {
        &lt;SPAN style="COLOR: #2b91af"&gt;Product &lt;/SPAN&gt;product = database.Products.Single(item =&amp;gt; item.ProductID == id); &lt;SPAN style="COLOR: green"&gt;// SELECT...
        &lt;/SPAN&gt;product.UnitPrice = unitPrice; &lt;SPAN style="COLOR: green"&gt;// UPDATE...
        &lt;/SPAN&gt;database.SubmitChanges();
    }
}&lt;/PRE&gt;
&lt;P&gt;Before updating an entity, that entity has to be retrieved by an extra SELECT query. This is slower than direct data update via ADO.NET:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;private static void &lt;/SPAN&gt;UpdateProductUnitPrice(&lt;SPAN style="COLOR: blue"&gt;int &lt;/SPAN&gt;id, &lt;SPAN style="COLOR: blue"&gt;decimal &lt;/SPAN&gt;unitPrice)
{
    &lt;SPAN style="COLOR: blue"&gt;using &lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;SqlConnection &lt;/SPAN&gt;connection = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;SqlConnection&lt;/SPAN&gt;(
        &lt;SPAN style="COLOR: #a31515"&gt;"Data Source=localhost;Initial Catalog=Northwind;Integrated Security=True"&lt;/SPAN&gt;))
    &lt;SPAN style="COLOR: blue"&gt;using &lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;SqlCommand &lt;/SPAN&gt;command = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;SqlCommand&lt;/SPAN&gt;(
        &lt;SPAN style="COLOR: #a31515"&gt;@"UPDATE [dbo].[Products] SET [UnitPrice] = @UnitPrice WHERE [ProductID] = @ProductID"&lt;/SPAN&gt;,
        connection))
    {
        command.Parameters.Add(&lt;SPAN style="COLOR: #a31515"&gt;"@ProductID"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #2b91af"&gt;SqlDbType&lt;/SPAN&gt;.Int).Value = id;
        command.Parameters.Add(&lt;SPAN style="COLOR: #a31515"&gt;"@UnitPrice"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #2b91af"&gt;SqlDbType&lt;/SPAN&gt;.Money).Value = unitPrice;

        connection.Open();
        command.Transaction = connection.BeginTransaction();
        command.ExecuteNonQuery(); &lt;SPAN style="COLOR: green"&gt;// UPDATE...
        &lt;/SPAN&gt;command.Transaction.Commit();
    }
}&lt;/PRE&gt;
&lt;P&gt;The above imperative code specifies the “how to do” details with better performance.&lt;/P&gt;
&lt;P&gt;For the same reason, some articles from Internet insist that, when updating data via LINQ to SQL, the above declarative code should be replaced by:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;private static void &lt;/SPAN&gt;UpdateProductUnitPrice(&lt;SPAN style="COLOR: blue"&gt;int &lt;/SPAN&gt;id, &lt;SPAN style="COLOR: blue"&gt;decimal &lt;/SPAN&gt;unitPrice)
{
    &lt;SPAN style="COLOR: blue"&gt;using &lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;NorthwindDataContext &lt;/SPAN&gt;database = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;NorthwindDataContext&lt;/SPAN&gt;())
    {
        database.ExecuteCommand(
            &lt;SPAN style="COLOR: #a31515"&gt;"UPDATE [dbo].[Products] SET [UnitPrice] = {0} WHERE [ProductID] = {1}"&lt;/SPAN&gt;,
            id, 
            unitPrice);
    }
}&lt;/PRE&gt;
&lt;P&gt;Or just create a stored procedure:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;CREATE PROCEDURE &lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;[dbo]&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;[UpdateProductUnitPrice]
&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;(
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@ProductID &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;INT&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@UnitPrice &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;MONEY
&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;)
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;AS
BEGIN
    BEGIN TRANSACTION 
    UPDATE &lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;[dbo]&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;[Products] &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;SET &lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;[UnitPrice] &lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;= &lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@UnitPrice &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;WHERE &lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;[ProductID] &lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;= &lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@ProductID
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;COMMIT TRANSACTION
END
&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;and map it as a method of NorthwindDataContext (explained in &lt;A href="http://weblogs.asp.net/dixin/archive/2010/03/29/understanding-linq-to-sql-1-object-relational-mapping.aspx" target=_blank mce_href="http://weblogs.asp.net/dixin/archive/2010/03/29/understanding-linq-to-sql-1-object-relational-mapping.aspx"&gt;this post&lt;/A&gt;):&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;private static void &lt;/SPAN&gt;UpdateProductUnitPrice(&lt;SPAN style="COLOR: blue"&gt;int &lt;/SPAN&gt;id, &lt;SPAN style="COLOR: blue"&gt;decimal &lt;/SPAN&gt;unitPrice)
{
    &lt;SPAN style="COLOR: blue"&gt;using &lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;NorthwindDataContext &lt;/SPAN&gt;database = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;NorthwindDataContext&lt;/SPAN&gt;())
    {
        database.UpdateProductUnitPrice(id, unitPrice);
    }
}&lt;/PRE&gt;
&lt;P&gt;As a normal trade off for O/R mapping, a decision has to be made between performance overhead and programming productivity according to the case. In a developer’s perspective, if O/R mapping is chosen, I consistently choose the declarative LINQ code, unless this kind of overhead is unacceptable. &lt;/P&gt;
&lt;H1&gt;Data retrieving overhead&lt;/H1&gt;
&lt;P&gt;After talking about the O/R mapping specific issue. Now look into the LINQ to SQL specific issues, for example, performance in the data retrieving process. The previous post has explained that the SQL &lt;U&gt;translating&lt;/U&gt; and &lt;U&gt;executing&lt;/U&gt; is complex. Actually, &lt;A href="http://blogs.msdn.com/b/charlie/archive/2007/08/06/linq-to-sql-pipeline-video-with-luca-bolognese-and-matt-warren.aspx" target=_blank mce_href="http://blogs.msdn.com/b/charlie/archive/2007/08/06/linq-to-sql-pipeline-video-with-luca-bolognese-and-matt-warren.aspx"&gt;the LINQ to SQL pipeline&lt;/A&gt; is similar to the compiler pipeline. It consists of about 15 steps to translate an C# expression tree to SQL statement, which can be categorized as:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;UL&gt;
&lt;LI&gt;Convert: Invoke SqlProvider.BuildQuery() to convert the tree of Expression nodes into a tree of SqlNode nodes; &lt;/LI&gt;
&lt;LI&gt;Bind: Used visitor pattern to figure out the meanings of names according to the mapping info, like a property for a column, etc.; &lt;/LI&gt;
&lt;LI&gt;Flatten: Figure out the hierarchy of the query; &lt;/LI&gt;
&lt;LI&gt;Rewrite: for SQL Server 2000, if needed &lt;/LI&gt;
&lt;LI&gt;Reduce: Remove the unnecessary information from the tree. &lt;/LI&gt;
&lt;LI&gt;Parameterize 
&lt;UL&gt;
&lt;LI&gt;Format: Generate the SQL statement string; &lt;/LI&gt;
&lt;LI&gt;Parameterize: Figure out the parameters, for example, a reference to a local variable should be a parameter in SQL; &lt;/LI&gt;
&lt;LI&gt;Materialize: Executes the reader and convert the result back into typed objects. &lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;So for each data retrieving, even for data retrieving which looks simple: &lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;private static &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Product&lt;/SPAN&gt;[] RetrieveProducts(&lt;SPAN style="COLOR: blue"&gt;int &lt;/SPAN&gt;productId)
{
    &lt;SPAN style="COLOR: blue"&gt;using &lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;NorthwindDataContext &lt;/SPAN&gt;database = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;NorthwindDataContext&lt;/SPAN&gt;())
    {
        &lt;SPAN style="COLOR: blue"&gt;return &lt;/SPAN&gt;database.Products.Where(product =&amp;gt; product.ProductID == productId)
                                .ToArray();
    }
}&lt;/PRE&gt;
&lt;P&gt;LINQ to SQL goes through above steps to translate and execute the query. Fortunately, there is a built-in way to cache the translated query.&lt;/P&gt;
&lt;H2&gt;Compiled query&lt;/H2&gt;
&lt;P&gt;When such a LINQ to SQL query is executed repeatedly, The CompiledQuery can be used to translate query for one time, and execute for multiple times:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;internal static class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;CompiledQueries
&lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: blue"&gt;private static readonly &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Func&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;NorthwindDataContext&lt;/SPAN&gt;, &lt;SPAN style="COLOR: blue"&gt;int&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #2b91af"&gt;Product&lt;/SPAN&gt;[]&amp;gt; _retrieveProducts = 
        &lt;SPAN style="COLOR: #2b91af"&gt;CompiledQuery&lt;/SPAN&gt;.Compile((&lt;SPAN style="COLOR: #2b91af"&gt;NorthwindDataContext &lt;/SPAN&gt;database, &lt;SPAN style="COLOR: blue"&gt;int &lt;/SPAN&gt;productId) =&amp;gt;
            database.Products.Where(product =&amp;gt; product.ProductID == productId).ToArray());

    &lt;SPAN style="COLOR: blue"&gt;internal static &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Product&lt;/SPAN&gt;[] RetrieveProducts(
        &lt;SPAN style="COLOR: blue"&gt;this &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;NorthwindDataContext &lt;/SPAN&gt;database, &lt;SPAN style="COLOR: blue"&gt;int &lt;/SPAN&gt;productId)
    {
        &lt;SPAN style="COLOR: blue"&gt;return &lt;/SPAN&gt;_retrieveProducts(database, productId);
    }
}&lt;/PRE&gt;
&lt;P&gt;The new version of RetrieveProducts() gets better performance, because only when _retrieveProducts is first time invoked, it internally invokes SqlProvider.Compile() to translate the query expression. And it also uses lock to make sure translating once in multi-threading scenarios.&lt;/P&gt;
&lt;H2&gt;Static SQL / stored procedures without translating&lt;/H2&gt;
&lt;P&gt;Another way to avoid the translating overhead is to use static SQL or stored procedures, just as the above examples. Because this is a functional programming series, this article not dive into. For the details, &lt;A href="http://en.wikipedia.org/wiki/Scott_Guthrie" target=_blank mce_href="http://en.wikipedia.org/wiki/Scott_Guthrie"&gt;Scott Guthrie&lt;/A&gt; already has some excellent articles:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="http://weblogs.asp.net/scottgu/archive/2007/08/16/linq-to-sql-part-6-retrieving-data-using-stored-procedures.aspx" mce_href="http://weblogs.asp.net/scottgu/archive/2007/08/16/linq-to-sql-part-6-retrieving-data-using-stored-procedures.aspx"&gt;LINQ to SQL (Part 6: Retrieving Data Using Stored Procedures)&lt;/A&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://weblogs.asp.net/scottgu/archive/2007/08/23/linq-to-sql-part-7-updating-our-database-using-stored-procedures.aspx" mce_href="http://weblogs.asp.net/scottgu/archive/2007/08/23/linq-to-sql-part-7-updating-our-database-using-stored-procedures.aspx"&gt;LINQ to SQL (Part 7: Updating our Database using Stored Procedures)&lt;/A&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://weblogs.asp.net/scottgu/archive/2007/08/27/linq-to-sql-part-8-executing-custom-sql-expressions.aspx" mce_href="http://weblogs.asp.net/scottgu/archive/2007/08/27/linq-to-sql-part-8-executing-custom-sql-expressions.aspx"&gt;LINQ to SQL (Part 8: Executing Custom SQL Expressions)&lt;/A&gt; &lt;/LI&gt;&lt;/UL&gt;
&lt;H1&gt;Data changing overhead&lt;/H1&gt;
&lt;P&gt;By looking into the data updating process, it also needs a lot of work:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Begins transaction &lt;/LI&gt;
&lt;LI&gt;Processes the changes (ChangeProcessor) 
&lt;UL&gt;
&lt;LI&gt;Walks through the objects to identify the changes &lt;/LI&gt;
&lt;LI&gt;Determines the order of the changes &lt;/LI&gt;
&lt;LI&gt;Executes the changings 
&lt;UL&gt;
&lt;LI&gt;LINQ queries may be needed to execute the changings, like the first example in this article, an object needs to be retrieved before changed, then &lt;U&gt;the above whole process&lt;/U&gt; of data retrieving will be went through &lt;/LI&gt;
&lt;LI&gt;If there is user customization, it will be executed, for example, a table’s INSERT / UPDATE / DELETE can be customized in the O/R designer &lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=image border=0 alt=image src="http://weblogs.asp.net/blogs/dixin/image_6DCBF16A.png" width=666 height=576 mce_src="http://weblogs.asp.net/blogs/dixin/image_6DCBF16A.png"&gt;&lt;/P&gt;
&lt;P&gt;It is important to keep these overhead in mind.&lt;/P&gt;
&lt;H2&gt;Bulk deleting / updating&lt;/H2&gt;
&lt;P&gt;Another thing to be aware is the bulk deleting:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;private static void&lt;/SPAN&gt; DeleteProducts(&lt;SPAN style="COLOR: blue"&gt;int &lt;/SPAN&gt;categoryId)
{
    &lt;SPAN style="COLOR: blue"&gt;using &lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;NorthwindDataContext &lt;/SPAN&gt;database = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;NorthwindDataContext&lt;/SPAN&gt;())
    {
        database.Products.DeleteAllOnSubmit(
            database.Products.Where(product =&amp;gt; product.CategoryID == categoryId));
        database.SubmitChanges();
    }
}&lt;/PRE&gt;
&lt;P&gt;The expected SQL should be like:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;BEGIN TRANSACTION 
exec &lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;sp_executesql &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'DELETE FROM [dbo].[Products] AS [t0]
WHERE [t0].[CategoryID] = @p0'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'@p0 int'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p0&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;9
&lt;SPAN style="COLOR: blue"&gt;COMMIT TRANSACTION
&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;Hoverer, as fore mentioned, the actual SQL is to retrieving the entities, and then delete them one by one:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: green"&gt;-- Retrieves the entities to be deleted:
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;exec &lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;sp_executesql &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'SELECT [t0].[ProductID], [t0].[ProductName], [t0].[SupplierID], [t0].[CategoryID], [t0].[QuantityPerUnit], [t0].[UnitPrice], [t0].[UnitsInStock], [t0].[UnitsOnOrder], [t0].[ReorderLevel], [t0].[Discontinued]
FROM [dbo].[Products] AS [t0]
WHERE [t0].[CategoryID] = @p0'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'@p0 int'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p0&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;9

&lt;SPAN style="COLOR: green"&gt;-- Deletes the retrieved entities one by one:
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;BEGIN TRANSACTION 
exec &lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;sp_executesql &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'DELETE FROM [dbo].[Products] WHERE ([ProductID] = @p0) AND ([ProductName] = @p1) AND ([SupplierID] IS NULL) AND ([CategoryID] = @p2) AND ([QuantityPerUnit] IS NULL) AND ([UnitPrice] = @p3) AND ([UnitsInStock] = @p4) AND ([UnitsOnOrder] = @p5) AND ([ReorderLevel] = @p6) AND (NOT ([Discontinued] = 1))'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'@p0 int,@p1 nvarchar(4000),@p2 int,@p3 money,@p4 smallint,@p5 smallint,@p6 smallint'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p0&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;78&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p1&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'Optimus Prime'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p2&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;9&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p3&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;$0.0000&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p4&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;0&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p5&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;0&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p6&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;0
&lt;SPAN style="COLOR: blue"&gt;exec &lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;sp_executesql &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'DELETE FROM [dbo].[Products] WHERE ([ProductID] = @p0) AND ([ProductName] = @p1) AND ([SupplierID] IS NULL) AND ([CategoryID] = @p2) AND ([QuantityPerUnit] IS NULL) AND ([UnitPrice] = @p3) AND ([UnitsInStock] = @p4) AND ([UnitsOnOrder] = @p5) AND ([ReorderLevel] = @p6) AND (NOT ([Discontinued] = 1))'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'@p0 int,@p1 nvarchar(4000),@p2 int,@p3 money,@p4 smallint,@p5 smallint,@p6 smallint'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p0&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;79&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p1&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'Bumble Bee'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p2&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;9&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p3&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;$0.0000&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p4&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;0&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p5&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;0&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p6&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;0
&lt;SPAN style="COLOR: green"&gt;-- ...
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;COMMIT TRANSACTION
&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;And the same to the bulk updating. This is really not effective and need to be aware. Here is already some solutions from the Internet, like &lt;A href="http://www.aneyfamily.com/terryandann/post/2008/04/Batch-Updates-and-Deletes-with-LINQ-to-SQL.aspx" target=_blank mce_href="http://www.aneyfamily.com/terryandann/post/2008/04/Batch-Updates-and-Deletes-with-LINQ-to-SQL.aspx"&gt;this one&lt;/A&gt;. The idea is wrap the above SELECT statement into a INNER JOIN:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;exec &lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;sp_executesql &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'DELETE [dbo].[Products] FROM [dbo].[Products] AS [j0] 
INNER JOIN (   
&lt;U&gt;SELECT [t0].[ProductID], [t0].[ProductName], [t0].[SupplierID], [t0].[CategoryID], [t0].[QuantityPerUnit], [t0].[UnitPrice], [t0].[UnitsInStock], [t0].[UnitsOnOrder], [t0].[ReorderLevel], [t0].[Discontinued]
FROM [dbo].[Products] AS [t0]
WHERE [t0].[CategoryID] = @p0&lt;/U&gt;) AS [j1] 
ON ([j0].[ProductID] = [j1].[[Products])'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;, &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;-- The Primary Key
&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'@p0 int'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p0&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;9&lt;/PRE&gt;
&lt;H1&gt;Query plan overhead&lt;/H1&gt;
&lt;P&gt;The last thing is about the SQL Server &lt;A href="http://en.wikipedia.org/wiki/Query_plan" target=_blank mce_href="http://en.wikipedia.org/wiki/Query_plan"&gt;query plan&lt;/A&gt;. Before .NET 4.0, LINQ to SQL has an issue (not sure if it is a bug). LINQ to SQL internally uses ADO.NET, but it does not set the SqlParameter.Size for a variable-length argument, like argument of NVARCHAR type, etc. So for two queries with the same SQL but different argument length:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;using &lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;NorthwindDataContext &lt;/SPAN&gt;database = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;NorthwindDataContext&lt;/SPAN&gt;())
{
    database.Products.Where(product =&amp;gt; product.ProductName == &lt;SPAN style="COLOR: #a31515"&gt;"&lt;U&gt;A&lt;/U&gt;"&lt;/SPAN&gt;)
        .Select(product =&amp;gt; product.ProductID).ToArray();

    &lt;SPAN style="COLOR: green"&gt;// The same SQL and argument type, different argument length.
    &lt;/SPAN&gt;database.Products.Where(product =&amp;gt; product.ProductName == &lt;SPAN style="COLOR: #a31515"&gt;"&lt;U&gt;AA&lt;/U&gt;"&lt;/SPAN&gt;)
        .Select(product =&amp;gt; product.ProductID).ToArray();
}&lt;/PRE&gt;
&lt;P&gt;Pay attention to the argument length in the translated SQL:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;exec &lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;sp_executesql &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'SELECT [t0].[ProductID]
FROM [dbo].[Products] AS [t0]
WHERE [t0].[ProductName] = @p0'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'@p0 &lt;U&gt;nvarchar(1)&lt;/U&gt;'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p0&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'A'

&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;exec &lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;sp_executesql &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'SELECT [t0].[ProductID]
FROM [dbo].[Products] AS [t0]
WHERE [t0].[ProductName] = @p0'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'@p0 &lt;U&gt;nvarchar(2)&lt;/U&gt;'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p0&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'AA'
&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;Here is the overhead: The first query’s query plan cache is not reused by the second one:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;SELECT &lt;/SPAN&gt;&lt;SPAN style="COLOR: lime"&gt;sys&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;&lt;SPAN style="COLOR: lime"&gt;syscacheobjects&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;cacheobjtype&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;, &lt;/SPAN&gt;&lt;SPAN style="COLOR: lime"&gt;sys&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;&lt;SPAN style="COLOR: lime"&gt;dm_exec_cached_plans&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;usecounts&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;, &lt;/SPAN&gt;&lt;SPAN style="COLOR: lime"&gt;sys&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;&lt;SPAN style="COLOR: lime"&gt;syscacheobjects&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;[sql] &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;FROM &lt;/SPAN&gt;&lt;SPAN style="COLOR: lime"&gt;sys&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;&lt;SPAN style="COLOR: lime"&gt;syscacheobjects
&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;INNER JOIN &lt;/SPAN&gt;&lt;SPAN style="COLOR: lime"&gt;sys&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;&lt;SPAN style="COLOR: lime"&gt;dm_exec_cached_plans
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;ON &lt;/SPAN&gt;&lt;SPAN style="COLOR: lime"&gt;sys&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;&lt;SPAN style="COLOR: lime"&gt;syscacheobjects&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;bucketid &lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;= &lt;/SPAN&gt;&lt;SPAN style="COLOR: lime"&gt;sys&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;&lt;SPAN style="COLOR: lime"&gt;dm_exec_cached_plans&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;bucketid&lt;SPAN style="COLOR: gray"&gt;; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=image border=0 alt=image src="http://weblogs.asp.net/blogs/dixin/image_539DF983.png" width=732 height=83 mce_src="http://weblogs.asp.net/blogs/dixin/image_539DF983.png"&gt;&lt;/P&gt;
&lt;P&gt;They actually use different query plans. Again, pay attention to the argument length in the [sql] column (@p0 nvarchar(2) / @p0 nvarchar(1)).&lt;/P&gt;
&lt;P&gt;Fortunately, in .NET 4.0 this is fixed:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;internal static class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;SqlTypeSystem
&lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: blue"&gt;private abstract class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ProviderBase &lt;/SPAN&gt;: &lt;SPAN style="COLOR: #2b91af"&gt;TypeSystemProvider
    &lt;/SPAN&gt;{
        &lt;SPAN style="COLOR: blue"&gt;protected int&lt;/SPAN&gt;? GetLargestDeclarableSize(&lt;SPAN style="COLOR: #2b91af"&gt;SqlType &lt;/SPAN&gt;declaredType)
        {
            &lt;SPAN style="COLOR: #2b91af"&gt;SqlDbType &lt;/SPAN&gt;sqlDbType = declaredType.SqlDbType;
            &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(sqlDbType &amp;lt;= &lt;SPAN style="COLOR: #2b91af"&gt;SqlDbType&lt;/SPAN&gt;.Image)
            {
                &lt;SPAN style="COLOR: blue"&gt;switch &lt;/SPAN&gt;(sqlDbType)
                {
                    &lt;SPAN style="COLOR: blue"&gt;case &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;SqlDbType&lt;/SPAN&gt;.Binary:
                    &lt;SPAN style="COLOR: blue"&gt;case &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;SqlDbType&lt;/SPAN&gt;.Image:
                        &lt;SPAN style="COLOR: blue"&gt;return &lt;/SPAN&gt;8000;
                }

                &lt;SPAN style="COLOR: blue"&gt;return null&lt;/SPAN&gt;;
            }

            &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(sqlDbType == &lt;U&gt;&lt;SPAN style="COLOR: #2b91af"&gt;SqlDbType&lt;/SPAN&gt;.NVarChar&lt;/U&gt;)
            {
                &lt;U&gt;&lt;SPAN style="COLOR: blue"&gt;return &lt;/SPAN&gt;4000&lt;/U&gt;; &lt;SPAN style="COLOR: green"&gt;// Max length for NVARCHAR.
            &lt;/SPAN&gt;}

            &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(sqlDbType != &lt;SPAN style="COLOR: #2b91af"&gt;SqlDbType&lt;/SPAN&gt;.VarChar)
            {
                &lt;SPAN style="COLOR: blue"&gt;return null&lt;/SPAN&gt;;
            }

            &lt;SPAN style="COLOR: blue"&gt;return &lt;/SPAN&gt;8000;
        }
    }
}&lt;/PRE&gt;
&lt;P&gt;In this above example, the translated SQL becomes:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;exec &lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;sp_executesql &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'SELECT [t0].[ProductID]
FROM [dbo].[Products] AS [t0]
WHERE [t0].[ProductName] = @p0'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'@p0 &lt;U&gt;nvarchar(4000)&lt;/U&gt;'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p0&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'A'

&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;exec &lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;sp_executesql &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'SELECT [t0].[ProductID]
FROM [dbo].[Products] AS [t0]
WHERE [t0].[ProductName] = @p0'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'@p0 &lt;U&gt;nvarchar(4000)&lt;/U&gt;'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p0&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'AA'
&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;So that they reuses the same query plan cache:&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=image border=0 alt=image src="http://weblogs.asp.net/blogs/dixin/image_0660D825.png" width=732 height=66 mce_src="http://weblogs.asp.net/blogs/dixin/image_0660D825.png"&gt;&lt;/P&gt;
&lt;P&gt;Now the [usecounts] column is 2.&lt;/P&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=7678430" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/dixin/archive/tags/.NET/default.aspx">.NET</category><category domain="http://weblogs.asp.net/dixin/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://weblogs.asp.net/dixin/archive/tags/LINQ/default.aspx">LINQ</category><category domain="http://weblogs.asp.net/dixin/archive/tags/SQL+Server/default.aspx">SQL Server</category><category domain="http://weblogs.asp.net/dixin/archive/tags/TSQL/default.aspx">TSQL</category><category domain="http://weblogs.asp.net/dixin/archive/tags/LINQ+via+C_2300_+Series/default.aspx">LINQ via C# Series</category><category domain="http://weblogs.asp.net/dixin/archive/tags/C_2300_+3.0/default.aspx">C# 3.0</category><category domain="http://weblogs.asp.net/dixin/archive/tags/LINQ+to+SQL/default.aspx">LINQ to SQL</category></item><item><title>A DirectoryCatalog class for Silverlight MEF (Managed Extensibility Framework)</title><link>http://weblogs.asp.net/dixin/archive/2011/01/28/a-directorycatalog-for-silverlight-mef-managed-extensibility-framework.aspx</link><pubDate>Sat, 29 Jan 2011 05:37:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:7691479</guid><dc:creator>Dixin</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/dixin/rsscomments.aspx?PostID=7691479</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/dixin/commentapi.aspx?PostID=7691479</wfw:comment><comments>http://weblogs.asp.net/dixin/archive/2011/01/28/a-directorycatalog-for-silverlight-mef-managed-extensibility-framework.aspx#comments</comments><description>&lt;P&gt;In the MEF (Managed Extension Framework) for .NET, there are useful ComposablePartCatalog implementations in System.ComponentModel.Composition.dll, like:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;System.ComponentModel.Composition.Hosting.AggregateCatalog &lt;/LI&gt;
&lt;LI&gt;System.ComponentModel.Composition.Hosting.AssemblyCatalog &lt;/LI&gt;
&lt;LI&gt;System.ComponentModel.Composition.Hosting.DirectoryCatalog &lt;/LI&gt;
&lt;LI&gt;System.ComponentModel.Composition.Hosting.TypeCatalog &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;While in Silverlight, there is a extra System.ComponentModel.Composition.Hosting.DeploymentCatalog. As a wrapper of AssemblyCatalog, it can load all assemblies in a XAP file in the web server side. Unfortunately, in silverlight there is no DirectoryCatalog to load a folder.&lt;/P&gt;
&lt;H1&gt;Background&lt;/H1&gt;
&lt;P&gt;There are scenarios that Silverlight application may need to load all XAP files in a folder in the web server side, for example:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;If the Silverlight application is extensible and supports plug-ins, there would be something like&amp;nbsp;a Plugins folder in the web server, and each pluin would be an individual XAP file in the folder. In this scenario, after the application is loaded and started up, it would like to load all XAP files in Plugins folder. &lt;/LI&gt;
&lt;LI&gt;If the aplication supports themes, there would be something like a Themes folder, and each theme would be an individual XAP file too. The application would also need to load all XAP files in Themes. &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;It is useful if we have a DirectoryCatalog:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: #2b91af"&gt;DirectoryCatalog &lt;/SPAN&gt;catalog = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;DirectoryCatalog&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #a31515"&gt;"/Plugins"&lt;/SPAN&gt;);
catalog.DownloadCompleted += (sender, e) =&amp;gt; { };
catalog.DownloadAsync();&lt;/PRE&gt;
&lt;P&gt;Obviously, the implementation of DirectoryCatalog is easy. It is just a collection of DeploymentCatalog class.&lt;/P&gt;
&lt;H1&gt;Retrieve file list from a directory&lt;/H1&gt;
&lt;P&gt;Of course, to retrieve file list from a web folder, the folder’s “Directory Browsing” feature must be enabled:&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=image border=0 alt=image src="http://weblogs.asp.net/blogs/dixin/image_71CB93DF.png" width=640 height=480 mce_src="http://weblogs.asp.net/blogs/dixin/image_71CB93DF.png"&gt;&lt;/P&gt;
&lt;P&gt;So when the folder is requested, it responses a list of its files and folders:&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=image border=0 alt=image src="http://weblogs.asp.net/blogs/dixin/image_227E9B8B.png" width=638 height=334 mce_src="http://weblogs.asp.net/blogs/dixin/image_227E9B8B.png"&gt;&lt;/P&gt;
&lt;P&gt;This is nothing but a simple HTML page:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;html&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;head&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;title&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;/SPAN&gt;localhost - /Folder/&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;title&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
    &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;head&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;body&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;h1&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;/SPAN&gt;localhost - /Folder/&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;h1&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;hr&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;pre&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;a &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;href&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="/"&amp;gt;&lt;/SPAN&gt;[To Parent Directory]&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;a&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;br&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;br&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
            &lt;/SPAN&gt;1/3/2011  7:22 PM   185 &lt;SPAN style="COLOR: blue"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;a &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;href&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="/Folder/File.txt"&amp;gt;&lt;/SPAN&gt;File.txt&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;a&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;br&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
            &lt;/SPAN&gt;1/3/2011  7:22 PM   &lt;SPAN style="COLOR: red"&gt;&amp;amp;lt;&lt;/SPAN&gt;dir&lt;SPAN style="COLOR: red"&gt;&amp;amp;gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;a &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;href&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="/Folder/Folder/"&amp;gt;&lt;/SPAN&gt;Folder&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;a&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;br&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
        &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;pre&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;hr&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
    &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;body&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;html&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;For the ASP.NET Deployment Server of Visual Studio, directory browsing is enabled by default:&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=image border=0 alt=image src="http://weblogs.asp.net/blogs/dixin/image_1D2FB4DA.png" width=640 height=331 mce_src="http://weblogs.asp.net/blogs/dixin/image_1D2FB4DA.png"&gt;&lt;/P&gt;
&lt;P&gt;The HTML &amp;lt;Body&amp;gt; is almost the same:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;body &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;bgcolor&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="white"&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;h2&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;i&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;/SPAN&gt;Directory Listing -- /ClientBin/&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;i&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;h2&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;hr &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="100%" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;size&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="1" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;color&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="silver"&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;pre&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;a &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;href&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="/"&amp;gt;&lt;/SPAN&gt;[To Parent Directory]&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;a&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
        &lt;/SPAN&gt;Thursday, January 27, 2011 11:51 PM 282,538 &lt;SPAN style="COLOR: blue"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;a &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;href&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Test.xap"&amp;gt;&lt;/SPAN&gt;Test.xap&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;a&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
        &lt;/SPAN&gt;Tuesday, January 04, 2011 02:06 AM  &lt;SPAN style="COLOR: red"&gt;&amp;amp;lt;&lt;/SPAN&gt;dir&lt;SPAN style="COLOR: red"&gt;&amp;amp;gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;a &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;href&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="TestFolder/"&amp;gt;&lt;/SPAN&gt;TestFolder&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;a&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
    &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;pre&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;hr &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="100%" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;size&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="1" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;color&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="silver"&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;b&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;/SPAN&gt;Version Information:&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;b&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;&amp;amp;nbsp;&lt;/SPAN&gt;ASP.NET Development Server 10.0.0.0 
&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;body&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;The only difference is, IIS’s links start with slash, but here the links do not.&lt;/P&gt;
&lt;P&gt;Here one way to get the file list is read the href attributes of the links:&lt;/P&gt;&lt;PRE class=code&gt;[&lt;SPAN style="COLOR: #2b91af"&gt;Pure&lt;/SPAN&gt;]
&lt;SPAN style="COLOR: blue"&gt;private &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;IEnumerable&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;Uri&lt;/SPAN&gt;&amp;gt; GetFilesFromDirectory(&lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;html)
{
    &lt;SPAN style="COLOR: #2b91af"&gt;Contract&lt;/SPAN&gt;.Requires(html != &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;);
    &lt;SPAN style="COLOR: #2b91af"&gt;Contract&lt;/SPAN&gt;.Ensures(&lt;SPAN style="COLOR: #2b91af"&gt;Contract&lt;/SPAN&gt;.Result&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;IEnumerable&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;Uri&lt;/SPAN&gt;&amp;gt;&amp;gt;() != &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;);

    &lt;SPAN style="COLOR: blue"&gt;return new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Regex&lt;/SPAN&gt;(
                    &lt;SPAN style="COLOR: #a31515"&gt;"&amp;lt;a href=\"(?&amp;lt;uriRelative&amp;gt;[^\"]*)\"&amp;gt;[^&amp;lt;]*&amp;lt;/a&amp;gt;"&lt;/SPAN&gt;,
                    &lt;SPAN style="COLOR: #2b91af"&gt;RegexOptions&lt;/SPAN&gt;.IgnoreCase | &lt;SPAN style="COLOR: #2b91af"&gt;RegexOptions&lt;/SPAN&gt;.CultureInvariant)
                .Matches(html)
                .OfType&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;Match&lt;/SPAN&gt;&amp;gt;()
                .Where(match =&amp;gt; match.Success)
                .Select(match =&amp;gt; match.Groups[&lt;SPAN style="COLOR: #a31515"&gt;"uriRelative"&lt;/SPAN&gt;].Value)
                .Where(uriRelative =&amp;gt; uriRelative.EndsWith(&lt;SPAN style="COLOR: #a31515"&gt;".xap"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #2b91af"&gt;StringComparison&lt;/SPAN&gt;.Ordinal))
                .Select(uriRelative =&amp;gt;
                    {
                        &lt;SPAN style="COLOR: #2b91af"&gt;Uri &lt;/SPAN&gt;baseUri = &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.Uri.IsAbsoluteUri
                                            ? &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.Uri
                                            : &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Uri&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;Application&lt;/SPAN&gt;.Current.Host.Source, &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.Uri);
                        uriRelative = uriRelative.StartsWith(&lt;SPAN style="COLOR: #a31515"&gt;"/"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #2b91af"&gt;StringComparison&lt;/SPAN&gt;.Ordinal)
                                            ? uriRelative
                                            : (baseUri.LocalPath.EndsWith(&lt;SPAN style="COLOR: #a31515"&gt;"/"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #2b91af"&gt;StringComparison&lt;/SPAN&gt;.Ordinal)
                                                    ? baseUri.LocalPath + uriRelative
                                                    : baseUri.LocalPath + &lt;SPAN style="COLOR: #a31515"&gt;"/" &lt;/SPAN&gt;+ uriRelative);
                        &lt;SPAN style="COLOR: blue"&gt;return new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Uri&lt;/SPAN&gt;(baseUri, uriRelative);
                    });
}&lt;/PRE&gt;
&lt;P&gt;Please notice the folders’ links end with a slash. They are filtered by the second Where() query.&lt;/P&gt;
&lt;P&gt;The above method can find files’ URIs from the specified IIS folder, or ASP.NET Deployment Server folder while debugging. To support other formats of file list, a constructor is needed to pass into a customized method:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: gray"&gt;/// &amp;lt;summary&amp;gt;
/// &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;Initializes a new instance of the &lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;&amp;lt;see cref="T:System.ComponentModel.Composition.Hosting.DirectoryCatalog" /&amp;gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;class with &lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;&amp;lt;see cref="T:System.ComponentModel.Composition.Primitives.ComposablePartDefinition" /&amp;gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;objects based on all the XAP files in the specified directory URI.
&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;/// &amp;lt;/summary&amp;gt;
/// &amp;lt;param name="uri"&amp;gt;
/// &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;URI to the directory to scan for XAPs to add to the catalog.
&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;/// &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;The URI must be absolute, or relative to &lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;&amp;lt;see cref="P:System.Windows.Interop.SilverlightHost.Source" /&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;.
&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;/// &amp;lt;/param&amp;gt;
/// &amp;lt;param name="getFilesFromDirectory"&amp;gt;
/// &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;The method to find files' URIs in the specified directory.
&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;/// &amp;lt;/param&amp;gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;DirectoryCatalog(&lt;SPAN style="COLOR: #2b91af"&gt;Uri &lt;/SPAN&gt;uri, &lt;SPAN style="COLOR: #2b91af"&gt;Func&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #2b91af"&gt;IEnumerable&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;Uri&lt;/SPAN&gt;&amp;gt;&amp;gt; &lt;U&gt;getFilesFromDirectory&lt;/U&gt;)
{
    &lt;SPAN style="COLOR: #2b91af"&gt;Contract&lt;/SPAN&gt;.Requires(uri != &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;);

    &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._uri = uri;
    &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._getFilesFromDirectory = getFilesFromDirectory ?? &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.GetFilesFromDirectory;
    &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._webClient = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Lazy&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;WebClient&lt;/SPAN&gt;&amp;gt;(() =&amp;gt; &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;WebClient&lt;/SPAN&gt;());

    &lt;SPAN style="COLOR: green"&gt;// Initializes other members.
&lt;/SPAN&gt;}&lt;/PRE&gt;
&lt;P&gt;When the getFilesFromDirectory parameter is null, the above GetFilesFromDirectory() method will be used as default.&lt;/P&gt;
&lt;H1&gt;Download the directory’s XAP file list&lt;/H1&gt;
&lt;P&gt;Now a public method can be created to start the downloading:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: gray"&gt;/// &amp;lt;summary&amp;gt;
/// &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;Begins downloading the XAP files in the directory.
&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;/// &amp;lt;/summary&amp;gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;public void &lt;/SPAN&gt;DownloadAsync()
{
    &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.ThrowIfDisposed();

    &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;Interlocked&lt;/SPAN&gt;.CompareExchange(&lt;SPAN style="COLOR: blue"&gt;ref this&lt;/SPAN&gt;._state, &lt;SPAN style="COLOR: #2b91af"&gt;State&lt;/SPAN&gt;.DownloadStarted, &lt;SPAN style="COLOR: #2b91af"&gt;State&lt;/SPAN&gt;.Created) == 0)
    {
        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._webClient.Value.OpenReadCompleted += &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.&lt;U&gt;HandleOpenReadCompleted&lt;/U&gt;;
        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._webClient.Value.OpenReadAsync(&lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.Uri, &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;);
    }
    &lt;SPAN style="COLOR: blue"&gt;else
    &lt;/SPAN&gt;{
        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.MutateStateOrThrow(&lt;SPAN style="COLOR: #2b91af"&gt;State&lt;/SPAN&gt;.DownloadCompleted, &lt;SPAN style="COLOR: #2b91af"&gt;State&lt;/SPAN&gt;.Initialized);
        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.OnDownloadCompleted(&lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;AsyncCompletedEventArgs&lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;, &lt;SPAN style="COLOR: blue"&gt;false&lt;/SPAN&gt;, &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;));
    }
}&lt;/PRE&gt;
&lt;P&gt;Here the HandleOpenReadCompleted() method is invoked when the file list HTML is downloaded.&lt;/P&gt;
&lt;H1&gt;Download all XAP files&lt;/H1&gt;
&lt;P&gt;After retrieving all files’ URIs, the next thing becomes even easier. HandleOpenReadCompleted() just uses built in DeploymentCatalog to download the XAPs, and aggregate them into one AggregateCatalog:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;private void &lt;/SPAN&gt;HandleOpenReadCompleted(&lt;SPAN style="COLOR: blue"&gt;object &lt;/SPAN&gt;sender, &lt;SPAN style="COLOR: #2b91af"&gt;OpenReadCompletedEventArgs &lt;/SPAN&gt;e)
{
    &lt;SPAN style="COLOR: #2b91af"&gt;Exception &lt;/SPAN&gt;error = e.Error;
    &lt;SPAN style="COLOR: blue"&gt;bool &lt;/SPAN&gt;cancelled = e.Cancelled;
    &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;Interlocked&lt;/SPAN&gt;.CompareExchange(&lt;SPAN style="COLOR: blue"&gt;ref this&lt;/SPAN&gt;._state, &lt;SPAN style="COLOR: #2b91af"&gt;State&lt;/SPAN&gt;.DownloadCompleted, &lt;SPAN style="COLOR: #2b91af"&gt;State&lt;/SPAN&gt;.DownloadStarted) !=
        &lt;SPAN style="COLOR: #2b91af"&gt;State&lt;/SPAN&gt;.DownloadStarted)
    {
        cancelled = &lt;SPAN style="COLOR: blue"&gt;true&lt;/SPAN&gt;;
    }

    &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(error == &lt;SPAN style="COLOR: blue"&gt;null &lt;/SPAN&gt;&amp;amp;&amp;amp; !cancelled)
    {
        &lt;SPAN style="COLOR: blue"&gt;try
        &lt;/SPAN&gt;{
            &lt;SPAN style="COLOR: blue"&gt;using &lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;StreamReader &lt;/SPAN&gt;reader = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;StreamReader&lt;/SPAN&gt;(e.Result))
            {
                &lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;html = reader.ReadToEnd();
                &lt;SPAN style="COLOR: #2b91af"&gt;IEnumerable&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;Uri&lt;/SPAN&gt;&amp;gt; uris = &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._getFilesFromDirectory(html);

                &lt;SPAN style="COLOR: #2b91af"&gt;Contract&lt;/SPAN&gt;.Assume(uris != &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;);

                &lt;SPAN style="COLOR: #2b91af"&gt;IEnumerable&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;DeploymentCatalog&lt;/SPAN&gt;&amp;gt; deploymentCatalogs =
                    uris.Select(uri =&amp;gt; &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;DeploymentCatalog&lt;/SPAN&gt;(uri));
                deploymentCatalogs.ForEach(
                    deploymentCatalog =&amp;gt;
                    {
                        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._aggregateCatalog.Catalogs.Add(deploymentCatalog);
                        deploymentCatalog.DownloadCompleted += &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.&lt;U&gt;HandleDownloadCompleted&lt;/U&gt;;
                    });
                deploymentCatalogs.ForEach(deploymentCatalog =&amp;gt; deploymentCatalog.DownloadAsync());
            }
        }
        &lt;SPAN style="COLOR: blue"&gt;catch &lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;Exception &lt;/SPAN&gt;exception)
        {
            error = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;InvalidOperationException&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;Resources&lt;/SPAN&gt;.InvalidOperationException_ErrorReadingDirectory, exception);
        }
    }

    &lt;SPAN style="COLOR: green"&gt;// Exception handling.&lt;/SPAN&gt;
}&lt;/PRE&gt;
&lt;P&gt;In HandleDownloadCompleted(), if all XAPs are downloaded without exception, OnDownloadCompleted() callback method will be invoked.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;private void &lt;/SPAN&gt;HandleDownloadCompleted(&lt;SPAN style="COLOR: blue"&gt;object &lt;/SPAN&gt;sender, &lt;SPAN style="COLOR: #2b91af"&gt;AsyncCompletedEventArgs &lt;/SPAN&gt;e)
{
    &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;Interlocked&lt;/SPAN&gt;.Increment(&lt;SPAN style="COLOR: blue"&gt;ref this&lt;/SPAN&gt;._downloaded) == &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._aggregateCatalog.Catalogs.Count)
    {
        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.OnDownloadCompleted(e);
    }
}&lt;/PRE&gt;
&lt;H1&gt;Exception handling&lt;/H1&gt;
&lt;P&gt;Whether this DirectoryCatelog can work only if the directory browsing feature is enabled. It is important to inform caller when directory cannot be browsed for XAP downloading.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;private void &lt;/SPAN&gt;HandleOpenReadCompleted(&lt;SPAN style="COLOR: blue"&gt;object &lt;/SPAN&gt;sender, &lt;SPAN style="COLOR: #2b91af"&gt;OpenReadCompletedEventArgs &lt;/SPAN&gt;e)
{
    &lt;SPAN style="COLOR: #2b91af"&gt;Exception &lt;/SPAN&gt;error = e.Error;
    &lt;SPAN style="COLOR: blue"&gt;bool &lt;/SPAN&gt;cancelled = e.Cancelled;
    &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;Interlocked&lt;/SPAN&gt;.CompareExchange(&lt;SPAN style="COLOR: blue"&gt;ref this&lt;/SPAN&gt;._state, &lt;SPAN style="COLOR: #2b91af"&gt;State&lt;/SPAN&gt;.DownloadCompleted, &lt;SPAN style="COLOR: #2b91af"&gt;State&lt;/SPAN&gt;.DownloadStarted) !=
        &lt;SPAN style="COLOR: #2b91af"&gt;State&lt;/SPAN&gt;.DownloadStarted)
    {
        cancelled = &lt;SPAN style="COLOR: blue"&gt;true&lt;/SPAN&gt;;
    }

    &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(error == &lt;SPAN style="COLOR: blue"&gt;null &lt;/SPAN&gt;&amp;amp;&amp;amp; !cancelled)
    {
        &lt;SPAN style="COLOR: blue"&gt;try
        &lt;/SPAN&gt;{
            &lt;SPAN style="COLOR: green"&gt;// No exception thrown when browsing directory. Downloads the listed XAPs.&lt;/SPAN&gt;
        }
        &lt;SPAN style="COLOR: blue"&gt;catch &lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;Exception &lt;/SPAN&gt;exception)
        {
            error = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;InvalidOperationException&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;Resources&lt;/SPAN&gt;.InvalidOperationException_ErrorReadingDirectory, exception);
        }
    }

    &lt;SPAN style="COLOR: #2b91af"&gt;WebException &lt;/SPAN&gt;webException = error &lt;SPAN style="COLOR: blue"&gt;as &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;WebException&lt;/SPAN&gt;;
    &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(webException != &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;)
    {
        &lt;SPAN style="COLOR: #2b91af"&gt;HttpWebResponse &lt;/SPAN&gt;webResponse = webException.Response &lt;SPAN style="COLOR: blue"&gt;as &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;HttpWebResponse&lt;/SPAN&gt;;
        &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(webResponse != &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;)
        {
            &lt;SPAN style="COLOR: green"&gt;// Internally, WebClient uses WebRequest.Create() to create the WebRequest object. Here does the same thing.
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;WebRequest &lt;/SPAN&gt;request = &lt;SPAN style="COLOR: #2b91af"&gt;WebRequest&lt;/SPAN&gt;.Create(&lt;SPAN style="COLOR: #2b91af"&gt;Application&lt;/SPAN&gt;.Current.Host.Source);

            &lt;SPAN style="COLOR: #2b91af"&gt;Contract&lt;/SPAN&gt;.Assume(request != &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;);

&lt;SPAN style="COLOR: green"&gt;            &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(request.CreatorInstance == &lt;SPAN style="COLOR: #2b91af"&gt;WebRequestCreator&lt;/SPAN&gt;.ClientHttp &amp;amp;&amp;amp;
                &lt;SPAN style="COLOR: green"&gt;// Silverlight is in client HTTP handling, all HTTP status codes are supported.
                &lt;/SPAN&gt;webResponse.StatusCode == &lt;SPAN style="COLOR: #2b91af"&gt;HttpStatusCode&lt;/SPAN&gt;.Forbidden)
            {
                &lt;SPAN style="COLOR: green"&gt;// When directory browsing is disabled, the HTTP status code is 403 (forbidden).
                &lt;/SPAN&gt;error = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;InvalidOperationException&lt;/SPAN&gt;(
                    &lt;SPAN style="COLOR: #2b91af"&gt;Resources&lt;/SPAN&gt;.InvalidOperationException_ErrorListingDirectory_ClientHttp, webException);
            }
            &lt;SPAN style="COLOR: blue"&gt;else if &lt;/SPAN&gt;(request.CreatorInstance == &lt;SPAN style="COLOR: #2b91af"&gt;WebRequestCreator&lt;/SPAN&gt;.BrowserHttp &amp;amp;&amp;amp;
                &lt;SPAN style="COLOR: green"&gt;// Silverlight is in browser HTTP handling, only 200 and 404 are supported.
                &lt;/SPAN&gt;webResponse.StatusCode == &lt;SPAN style="COLOR: #2b91af"&gt;HttpStatusCode&lt;/SPAN&gt;.NotFound)
            {
                &lt;SPAN style="COLOR: green"&gt;// When directory browsing is disabled, the HTTP status code is 404 (not found).
                &lt;/SPAN&gt;error = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;InvalidOperationException&lt;/SPAN&gt;(
                    &lt;SPAN style="COLOR: #2b91af"&gt;Resources&lt;/SPAN&gt;.InvalidOperationException_ErrorListingDirectory_BrowserHttp, webException);
            }
        }
    }

    &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.OnDownloadCompleted(&lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;AsyncCompletedEventArgs&lt;/SPAN&gt;(error, cancelled, &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;));
}&lt;/PRE&gt;
&lt;P&gt;Please notice Silverlight 3+ application can work in&amp;nbsp;&lt;A href="http://msdn.microsoft.com/en-us/library/dd920295.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/dd920295.aspx"&gt;either client HTTP handling, or browser HTTP handling&lt;/A&gt;. One difference is:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;In browser HTTP handling, only HTTP status code 200 (OK) and 404 (not OK, including 500, 403, etc.) are supported&lt;/LI&gt;
&lt;LI&gt;In client HTTP handling, all HTTP status code are supported&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;So in above code, exceptions in 2 modes are handled differently.&lt;/P&gt;
&lt;H1&gt;Conclusion&lt;/H1&gt;
&lt;P&gt;Here is the whole DirectoryCatelog’s looking:&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=image border=0 alt=image src="http://weblogs.asp.net/blogs/dixin/image_263C405B.png" width=469 height=917 mce_src="http://weblogs.asp.net/blogs/dixin/image_263C405B.png"&gt;&lt;/P&gt;
&lt;P&gt;Please &lt;A href="http://weblogs.asp.net/blogs/dixin/SilverlightMefExtensions.zip" target=_blank mce_href="http://weblogs.asp.net/blogs/dixin/SilverlightMefExtensions.zip"&gt;click here to download the source code&lt;/A&gt;, a simple unit test is included. This is a rough implementation. And, for convenience, some design and coding are just following the built in AggregateCatalog class and Deployment class. Please feel free to modify the code, and please kindly tell me if any issue is found.&lt;/P&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=7691479" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/dixin/archive/tags/.NET/default.aspx">.NET</category><category domain="http://weblogs.asp.net/dixin/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://weblogs.asp.net/dixin/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://weblogs.asp.net/dixin/archive/tags/Silverlight/default.aspx">Silverlight</category><category domain="http://weblogs.asp.net/dixin/archive/tags/MEF/default.aspx">MEF</category></item><item><title>Microsoft Chinese Spring Festival Celebration (2)</title><link>http://weblogs.asp.net/dixin/archive/2011/01/25/microsoft-chinese-spring-festival-celebration-2.aspx</link><pubDate>Tue, 25 Jan 2011 08:59:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:7689520</guid><dc:creator>Dixin</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/dixin/rsscomments.aspx?PostID=7689520</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/dixin/commentapi.aspx?PostID=7689520</wfw:comment><comments>http://weblogs.asp.net/dixin/archive/2011/01/25/microsoft-chinese-spring-festival-celebration-2.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Qi_Lu" target="_blank" mce_href="http://en.wikipedia.org/wiki/Qi_Lu"&gt;Qi Lu&lt;/a&gt;, Microsoft &lt;a href="http://www.microsoft.com/presspass/exec/lu/" target="_blank" mce_href="http://www.microsoft.com/presspass/exec/lu/"&gt;President&lt;/a&gt;:&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_0713" border="0" alt="DSC_0713" src="http://weblogs.asp.net/blogs/dixin/DSC_0713_30BF2965.jpg" width="434" height="653" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0713_30BF2965.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;Made in Taiwan:&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_0743" border="0" alt="DSC_0743" src="http://weblogs.asp.net/blogs/dixin/DSC_0743_7114CCD2.jpg" width="640" height="426" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0743_7114CCD2.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_0744" border="0" alt="DSC_0744" src="http://weblogs.asp.net/blogs/dixin/DSC_0744_6191BB03.jpg" width="640" height="426" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0744_6191BB03.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_0751" border="0" alt="DSC_0751" src="http://weblogs.asp.net/blogs/dixin/DSC_0751_0E3A74DD.jpg" width="640" height="426" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0751_0E3A74DD.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;Amazing Microsoft &lt;a href="http://en.wikipedia.org/wiki/Bing_(search_engine)" target="_blank" mce_href="http://en.wikipedia.org/wiki/Bing_(search_engine)"&gt;Bing&lt;/a&gt; team:&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_0784" border="0" alt="DSC_0784" src="http://weblogs.asp.net/blogs/dixin/DSC_0784_37CE4010.jpg" width="640" height="426" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0784_37CE4010.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_0790" border="0" alt="DSC_0790" src="http://weblogs.asp.net/blogs/dixin/DSC_0790_6476F9E9.jpg" width="640" height="426" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0790_6476F9E9.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_0785" border="0" alt="DSC_0785" src="http://weblogs.asp.net/blogs/dixin/DSC_0785_7C2E314F.jpg" width="640" height="411" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0785_7C2E314F.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;Chinese Kungfu:&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_0808" border="0" alt="DSC_0808" src="http://weblogs.asp.net/blogs/dixin/DSC_0808_08BBDE6C.jpg" width="640" height="426" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0808_08BBDE6C.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_0815" border="0" alt="DSC_0815" src="http://weblogs.asp.net/blogs/dixin/DSC_0815_0777458D.jpg" width="640" height="426" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0815_0777458D.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;Microsoft rocks:&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_0840" border="0" alt="DSC_0840" src="http://weblogs.asp.net/blogs/dixin/DSC_0840_198F70B9.jpg" width="640" height="426" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0840_198F70B9.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_0842" border="0" alt="DSC_0842" src="http://weblogs.asp.net/blogs/dixin/DSC_0842_184AD7DA.jpg" width="640" height="426" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0842_184AD7DA.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;Rap with my soul: I grow up with Microsoft.&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_0854" border="0" alt="DSC_0854" src="http://weblogs.asp.net/blogs/dixin/DSC_0854_04BD7839.jpg" width="640" height="426" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0854_04BD7839.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_0868" border="0" alt="DSC_0868" src="http://weblogs.asp.net/blogs/dixin/DSC_0868_04EE13CF.jpg" width="640" height="426" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0868_04EE13CF.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_0887" border="0" alt="DSC_0887" src="http://weblogs.asp.net/blogs/dixin/DSC_0887_5CDB64AF.jpg" width="640" height="426" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0887_5CDB64AF.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_0795" border="0" alt="DSC_0795" src="http://weblogs.asp.net/blogs/dixin/DSC_0795_34C8B590.jpg" width="319" height="480" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0795_34C8B590.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_0899" border="0" alt="DSC_0899" src="http://weblogs.asp.net/blogs/dixin/DSC_0899_73BA362B.jpg" width="319" height="480" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0899_73BA362B.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_0901" border="0" alt="DSC_0901" src="http://weblogs.asp.net/blogs/dixin/DSC_0901_04BE640F.jpg" width="319" height="480" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0901_04BE640F.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_0921" border="0" alt="DSC_0921" src="http://weblogs.asp.net/blogs/dixin/DSC_0921_38865A60.jpg" width="640" height="426" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0921_38865A60.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_0924" border="0" alt="DSC_0924" src="http://weblogs.asp.net/blogs/dixin/DSC_0924_3D88980F.jpg" width="640" height="426" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0924_3D88980F.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_0926" border="0" alt="DSC_0926" src="http://weblogs.asp.net/blogs/dixin/DSC_0926_553FCF75.jpg" width="640" height="426" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0926_553FCF75.jpg" /&gt;&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=7689520" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/dixin/archive/tags/Microsoft+Redmond+Campus/default.aspx">Microsoft Redmond Campus</category><category domain="http://weblogs.asp.net/dixin/archive/tags/Microsoft/default.aspx">Microsoft</category></item><item><title>Microsoft Chinese Spring Festival Celebration (1)</title><link>http://weblogs.asp.net/dixin/archive/2011/01/24/microsoft-chinese-spring-festival-celebration-1.aspx</link><pubDate>Mon, 24 Jan 2011 08:46:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:7688794</guid><dc:creator>Dixin</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/dixin/rsscomments.aspx?PostID=7688794</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/dixin/commentapi.aspx?PostID=7688794</wfw:comment><comments>http://weblogs.asp.net/dixin/archive/2011/01/24/microsoft-chinese-spring-festival-celebration-1.aspx#comments</comments><description>&lt;P&gt;Last night there was a big party in Redmond: &lt;A href="http://www.microsoftchime.org/?q=node/4" target=_blank mce_href="http://www.microsoftchime.org/?q=node/4"&gt;Microsoft Spring Festival Celebration&lt;/A&gt;. It is organized by &lt;A href="http://www.microsoftchime.org/" target=_blank mce_href="http://www.microsoftchime.org/"&gt;Chime&lt;/A&gt; (an employee network group in Microsoft), and it is also the biggest &lt;A href="http://en.wikipedia.org/wiki/Chinese_New_Year" target=_blank mce_href="http://en.wikipedia.org/wiki/Chinese_New_Year"&gt;Chinese new year&lt;/A&gt; celebration in Seattle area. Thousands of people attended the party, including &lt;A href="http://en.wikipedia.org/wiki/Steve_Ballmer" target=_blank mce_href="http://en.wikipedia.org/wiki/Steve_Ballmer"&gt;Steve Ballmer&lt;/A&gt;. I also brought my powerful &lt;A href="http://en.wikipedia.org/wiki/Nikon_D700" target=_blank mce_href="http://en.wikipedia.org/wiki/Nikon_D700"&gt;Nikon D700&lt;/A&gt; there.&lt;/P&gt;
&lt;P&gt;Before the grand celebration show:&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=DSC_0568 border=0 alt=DSC_0568 src="http://weblogs.asp.net/blogs/dixin/DSC_0568_501ADF79.jpg" width=640 height=426 mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0568_501ADF79.jpg"&gt;&lt;/P&gt;
&lt;P&gt;Greetings from Microsoft:&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=DSC_0546 border=0 alt=DSC_0546 src="http://weblogs.asp.net/blogs/dixin/DSC_0546_6EF15357.jpg" width=640 height=426 mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0546_6EF15357.jpg"&gt;&lt;/P&gt;
&lt;P&gt;The opening, Chinese movie medley:&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=DSC_0576 border=0 alt=DSC_0576 src="http://weblogs.asp.net/blogs/dixin/DSC_0576_18F15180.jpg" width=640 height=426 mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0576_18F15180.jpg"&gt;&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=DSC_0603 border=0 alt=DSC_0603 src="http://weblogs.asp.net/blogs/dixin/DSC_0603_50C395A3.jpg" width=640 height=489 mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0603_50C395A3.jpg"&gt;&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=DSC_0601 border=0 alt=DSC_0601 src="http://weblogs.asp.net/blogs/dixin/DSC_0601_6B8FBBAF.jpg" width=640 height=426 mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0601_6B8FBBAF.jpg"&gt;&lt;/P&gt;
&lt;P&gt;Microsoft MCs:&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=DSC_0606 border=0 alt=DSC_0606 src="http://weblogs.asp.net/blogs/dixin/DSC_0606_34662DB6.jpg" width=640 height=426 mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0606_34662DB6.jpg"&gt;&lt;/P&gt;
&lt;P&gt;Talk Show: Microsoft, Welcome to Beijing!&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=DSC_0607 border=0 alt=DSC_0607 src="http://weblogs.asp.net/blogs/dixin/DSC_0607_0C537E97.jpg" width=640 height=426 mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0607_0C537E97.jpg"&gt;&lt;/P&gt;
&lt;P&gt;Bing!&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=DSC_0608 border=0 alt=DSC_0608 src="http://weblogs.asp.net/blogs/dixin/DSC_0608_77EDB90B.jpg" width=640 height=426 mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0608_77EDB90B.jpg"&gt;&lt;/P&gt;
&lt;P&gt;Dancing, happy new year:&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=DSC_0611 border=0 alt=DSC_0611 src="http://weblogs.asp.net/blogs/dixin/DSC_0611_7DC85CA4.jpg" width=640 height=426 mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0611_7DC85CA4.jpg"&gt;&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=DSC_0612 border=0 alt=DSC_0612 src="http://weblogs.asp.net/blogs/dixin/DSC_0612_4E96710D.jpg" width=640 height=426 mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0612_4E96710D.jpg"&gt;&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=DSC_0616 border=0 alt=DSC_0616 src="http://weblogs.asp.net/blogs/dixin/DSC_0616_0668B531.jpg" width=640 height=425 mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0616_0668B531.jpg"&gt;&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=DSC_0614 border=0 alt=DSC_0614 src="http://weblogs.asp.net/blogs/dixin/DSC_0614_0C4358CA.jpg" width=640 height=426 mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0614_0C4358CA.jpg"&gt;&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=DSC_0623 border=0 alt=DSC_0623 src="http://weblogs.asp.net/blogs/dixin/DSC_0623_79222C1D.jpg" width=640 height=419 mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0623_79222C1D.jpg"&gt;&lt;/P&gt;
&lt;P&gt;Greetings to everyone:&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=DSC_0624 border=0 alt=DSC_0624 src="http://weblogs.asp.net/blogs/dixin/DSC_0624_6A0B4D43.jpg" width=640 height=413 mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0624_6A0B4D43.jpg"&gt;&lt;/P&gt;
&lt;P&gt;&lt;A href="http://en.wikipedia.org/wiki/Harry_Shum" target=_blank mce_href="http://en.wikipedia.org/wiki/Harry_Shum"&gt;Harry Shum&lt;/A&gt;, Microsoft &lt;A href="http://www.microsoft.com/presspass/exec/Shum/" target=_blank mce_href="http://www.microsoft.com/presspass/exec/Shum/"&gt;Vice President&lt;/A&gt;:&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=DSC_0627 border=0 alt=DSC_0627 src="http://weblogs.asp.net/blogs/dixin/DSC_0627_08E1C122.jpg" width=640 height=426 mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0627_08E1C122.jpg"&gt;&lt;/P&gt;
&lt;P&gt;Next is &lt;A href="http://en.wikipedia.org/wiki/Steve_Ballmer" target=_blank mce_href="http://en.wikipedia.org/wiki/Steve_Ballmer"&gt;Steve Baller&lt;/A&gt;, Microsoft &lt;A href="http://www.microsoft.com/presspass/exec/steve/default.aspx" target=_blank mce_href="http://www.microsoft.com/presspass/exec/steve/default.aspx"&gt;CEO&lt;/A&gt;:&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=DSC_0631 border=0 alt=DSC_0631 src="http://weblogs.asp.net/blogs/dixin/DSC_0631_0EBC64BB.jpg" width=640 height=426 mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0631_0EBC64BB.jpg"&gt;&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=DSC_0632 border=0 alt=DSC_0632 src="http://weblogs.asp.net/blogs/dixin/DSC_0632_7FA585E0.jpg" width=640 height=426 mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0632_7FA585E0.jpg"&gt;&lt;/P&gt;
&lt;P&gt;I have some lucky money for you:&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=DSC_0637 border=0 alt=DSC_0637 src="http://weblogs.asp.net/blogs/dixin/DSC_0637_7A569F2F.jpg" width=640 height=426 mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0637_7A569F2F.jpg"&gt;&lt;/P&gt;
&lt;P&gt;You want this red envelope?&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=DSC_0642 border=0 alt=DSC_0642 src="http://weblogs.asp.net/blogs/dixin/DSC_0642_043B909B.jpg" width=640 height=425 mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0642_043B909B.jpg"&gt;&lt;/P&gt;
&lt;P&gt;Come and get it!!!&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=DSC_0643 border=0 alt=DSC_0643 src="http://weblogs.asp.net/blogs/dixin/DSC_0643_50FF5731.jpg" width=640 height=426 mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0643_50FF5731.jpg"&gt;&lt;/P&gt;
&lt;P&gt;Come on!!!&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=DSC_0644 border=0 alt=DSC_0644 src="http://weblogs.asp.net/blogs/dixin/DSC_0644_5AE4489C.jpg" width=640 height=426 mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0644_5AE4489C.jpg"&gt;&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=DSC_0654 border=0 alt=DSC_0654 src="http://weblogs.asp.net/blogs/dixin/DSC_0654_60BEEC35.jpg" width=640 height=426 mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0654_60BEEC35.jpg"&gt;&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=DSC_0656 border=0 alt=DSC_0656 src="http://weblogs.asp.net/blogs/dixin/DSC_0656_2D82B2CC.jpg" width=640 height=426 mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0656_2D82B2CC.jpg"&gt;&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=DSC_0659 border=0 alt=DSC_0659 src="http://weblogs.asp.net/blogs/dixin/DSC_0659_6C080072.jpg" width=640 height=426 mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0659_6C080072.jpg"&gt;&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=DSC_0663 border=0 alt=DSC_0663 src="http://weblogs.asp.net/blogs/dixin/DSC_0663_222978C2.jpg" width=640 height=964 mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0663_222978C2.jpg"&gt;&lt;/P&gt;
&lt;P&gt;He was moving so fast, and the photo is blurred:&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=DSC_0684 border=0 alt=DSC_0684 src="http://weblogs.asp.net/blogs/dixin/DSC_0684_745BAFFC.jpg" width=640 height=425 mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0684_745BAFFC.jpg"&gt;&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=DSC_0685 border=0 alt=DSC_0685 src="http://weblogs.asp.net/blogs/dixin/DSC_0685_334D3098.jpg" width=640 height=425 mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0685_334D3098.jpg"&gt;&lt;/P&gt;
&lt;P&gt;I have red envelopes for every one:&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=DSC_0690 border=0 alt=DSC_0690 src="http://weblogs.asp.net/blogs/dixin/DSC_0690_0B3A8179.jpg" width=640 height=465 mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0690_0B3A8179.jpg"&gt;&lt;/P&gt;
&lt;P&gt;Happy Chinese new year!!!&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=DSC_0670 border=0 alt=DSC_0670 src="http://weblogs.asp.net/blogs/dixin/DSC_0670_151F72E4.jpg" width=640 height=413 mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0670_151F72E4.jpg"&gt;&lt;/P&gt;
&lt;P&gt;That’s me, hiding in the front row :)&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=DSC_0682 border=0 alt=DSC_0682 src="http://weblogs.asp.net/blogs/dixin/DSC_0682_4E488257.jpg" width=640 height=426 mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0682_4E488257.jpg"&gt;&lt;/P&gt;
&lt;P&gt;Click &lt;A href="http://weblogs.asp.net/dixin/archive/2011/01/25/microsoft-chinese-spring-festival-celebration-2.aspx" target=_blank mce_href="http://weblogs.asp.net/dixin/archive/2011/01/25/microsoft-chinese-spring-festival-celebration-2.aspx"&gt;here to view Part 2&lt;/A&gt;.&lt;/P&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=7688794" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/dixin/archive/tags/Microsoft+Redmond+Campus/default.aspx">Microsoft Redmond Campus</category><category domain="http://weblogs.asp.net/dixin/archive/tags/Microsoft/default.aspx">Microsoft</category></item><item><title>The Humor of Silverlight</title><link>http://weblogs.asp.net/dixin/archive/2010/12/11/the-humor-of-silverlight.aspx</link><pubDate>Sat, 11 Dec 2010 04:35:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:7659747</guid><dc:creator>Dixin</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/dixin/rsscomments.aspx?PostID=7659747</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/dixin/commentapi.aspx?PostID=7659747</wfw:comment><comments>http://weblogs.asp.net/dixin/archive/2010/12/11/the-humor-of-silverlight.aspx#comments</comments><description>&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE: none; BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px; PADDING-TOP: 0px" title=image border=0 alt=image src="http://weblogs.asp.net/blogs/dixin/image_0E82AE99.png" width=482 height=184 mce_src="http://weblogs.asp.net/blogs/dixin/image_0E82AE99.png"&gt;&lt;/P&gt;
&lt;P&gt;Silverlight must be kidding.&lt;/P&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=7659747" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/dixin/archive/tags/.NET/default.aspx">.NET</category><category domain="http://weblogs.asp.net/dixin/archive/tags/Web/default.aspx">Web</category><category domain="http://weblogs.asp.net/dixin/archive/tags/Silverlight/default.aspx">Silverlight</category></item><item><title>Arrival to Redmond</title><link>http://weblogs.asp.net/dixin/archive/2010/10/29/arrival-to-redmond.aspx</link><pubDate>Thu, 28 Oct 2010 23:47:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:7633829</guid><dc:creator>Dixin</dc:creator><slash:comments>9</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/dixin/rsscomments.aspx?PostID=7633829</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/dixin/commentapi.aspx?PostID=7633829</wfw:comment><comments>http://weblogs.asp.net/dixin/archive/2010/10/29/arrival-to-redmond.aspx#comments</comments><description>&lt;p&gt;In this year, I was rewarded as an &lt;a href="http://weblogs.asp.net/dixin/archive/2010/10/28/microsoft-most-valuable-professional-kit-unboxing.aspx" target="_blank" mce_href="http://weblogs.asp.net/dixin/archive/2010/10/28/microsoft-most-valuable-professional-kit-unboxing.aspx"&gt;MVP on C# of Year 2010&lt;/a&gt;; at the same time, 3 different groups of Microsoft offered me 3 SDEII positions, and I made my choice. Now, with the help of Microsoft, I just relocated from China to Redmond. &lt;/p&gt;  &lt;p&gt;2 years ago, when I left Redmond, I decided that &lt;a href="http://en.wikipedia.org/wiki/I'll_be_back" target="_blank" mce_href="http://en.wikipedia.org/wiki/I&amp;#39;ll_be_back"&gt;I’ll be back&lt;/a&gt;. Now everything just looks the same as &lt;a href="http://weblogs.asp.net/dixin/archive/tags/Working+in+Redmond+Campus/default.aspx" target="_blank" mce_href="http://weblogs.asp.net/dixin/archive/tags/Working+in+Redmond+Campus/default.aspx"&gt;2 years ago&lt;/a&gt;. What a familiar place!&lt;/p&gt;  &lt;p&gt;As a great company, Microsoft also offers me very nice temp housing. It is &lt;a href="http://maps.google.com/maps/place?hl=en&amp;amp;expIds=17259,23756,24692,24813,24878,24879,26637,27182&amp;amp;sugexp=ldymls&amp;amp;xhr=t&amp;amp;cp=6&amp;amp;newwindow=1&amp;amp;rls=com.microsoft:en-us&amp;amp;wrapid=tljp128822929241300&amp;amp;um=1&amp;amp;ie=UTF-8&amp;amp;q=timberlawn+apartments&amp;amp;fb=1&amp;amp;gl=us&amp;amp;hq=timberlawn+apartments&amp;amp;hnear=Kirkland,+WA&amp;amp;cid=10746548189430292303" target="_blank" mce_href="http://maps.google.com/maps/place?hl=en&amp;amp;expIds=17259,23756,24692,24813,24878,24879,26637,27182&amp;amp;sugexp=ldymls&amp;amp;xhr=t&amp;amp;cp=6&amp;amp;newwindow=1&amp;amp;rls=com.microsoft:en-us&amp;amp;wrapid=tljp128822929241300&amp;amp;um=1&amp;amp;ie=UTF-8&amp;amp;q=timberlawn+apartments&amp;amp;fb=1&amp;amp;gl=us&amp;amp;hq=timberlawn+apartments&amp;amp;hnear=Kirkland,+WA&amp;amp;cid=10746548189430292303"&gt;an apartment&lt;/a&gt; 2-minutes-walk away from my office, and it is &lt;font style="background-color: #ffff00"&gt;free&lt;/font&gt; for 60 days!&lt;/p&gt;  &lt;p&gt;The apartment is on the 2nd floor:&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_0186" border="0" alt="DSC_0186" src="http://weblogs.asp.net/blogs/dixin/DSC_0186_336D1E31.jpg" width="640" height="425" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0186_336D1E31.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;The living room:&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_0287" border="0" alt="DSC_0287" src="http://weblogs.asp.net/blogs/dixin/DSC_0287_6A66FC6A.jpg" width="640" height="426" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0287_6A66FC6A.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_0292" border="0" alt="DSC_0292" src="http://weblogs.asp.net/blogs/dixin/DSC_0292_2F9F5394.jpg" width="640" height="426" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0292_2F9F5394.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;The dining room:&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="DSC_0283" border="0" alt="DSC_0283" src="http://weblogs.asp.net/blogs/dixin/DSC_0283_15831D14.jpg" width="640" height="426" /&gt;&lt;/p&gt;  &lt;p&gt;The balcony:&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_0288" border="0" alt="DSC_0288" src="http://weblogs.asp.net/blogs/dixin/DSC_0288_5B6FA783.jpg" width="640" height="426" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0288_5B6FA783.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;The master bedroom:&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_0293" border="0" alt="DSC_0293" src="http://weblogs.asp.net/blogs/dixin/DSC_0293_39379BFD.jpg" width="640" height="426" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0293_39379BFD.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_0203" border="0" alt="DSC_0203" src="http://weblogs.asp.net/blogs/dixin/DSC_0203_5735A9F1.jpg" width="640" height="425" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0203_5735A9F1.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;The storage room in the master bedroom:&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_0295" border="0" alt="DSC_0295" src="http://weblogs.asp.net/blogs/dixin/DSC_0295_676171EA.jpg" width="319" height="480" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0295_676171EA.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;The second bedroom:&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_0291" border="0" alt="DSC_0291" src="http://weblogs.asp.net/blogs/dixin/DSC_0291_18147996.jpg" width="640" height="426" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0291_18147996.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_0290" border="0" alt="DSC_0290" src="http://weblogs.asp.net/blogs/dixin/DSC_0290_0B3A2378.jpg" width="640" height="426" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0290_0B3A2378.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;The laundry room:&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_0197" border="0" alt="DSC_0197" src="http://weblogs.asp.net/blogs/dixin/DSC_0197_10A8941C.jpg" width="640" height="425" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0197_10A8941C.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;The left one is the dryer, and the right one is the washer.&lt;/p&gt;  &lt;p&gt;The utility room:&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_0196" border="0" alt="DSC_0196" src="http://weblogs.asp.net/blogs/dixin/DSC_0196_3A3C5F4F.jpg" width="319" height="480" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0196_3A3C5F4F.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;The bathroom is very nice and clean:&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_0198" border="0" alt="DSC_0198" src="http://weblogs.asp.net/blogs/dixin/DSC_0198_11BD7D3B.jpg" width="640" height="425" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0198_11BD7D3B.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_0200" border="0" alt="DSC_0200" src="http://weblogs.asp.net/blogs/dixin/DSC_0200_4BCC4A1A.jpg" width="319" height="480" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0200_4BCC4A1A.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;The kitchen:&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_0212" border="0" alt="DSC_0212" src="http://weblogs.asp.net/blogs/dixin/DSC_0212_039E8E3E.jpg" width="319" height="480" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0212_039E8E3E.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_0213" border="0" alt="DSC_0213" src="http://weblogs.asp.net/blogs/dixin/DSC_0213_4D4D662E.jpg" width="640" height="425" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0213_4D4D662E.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_0220" border="0" alt="DSC_0220" src="http://weblogs.asp.net/blogs/dixin/DSC_0220_1938C6DB.jpg" width="640" height="425" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0220_1938C6DB.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_0297" border="0" alt="DSC_0297" src="http://weblogs.asp.net/blogs/dixin/DSC_0297_0BF23DC8.jpg" width="511" height="768" mce_src="http://weblogs.asp.net/blogs/dixin/DSC_0297_0BF23DC8.jpg" /&gt;&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=7633829" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/dixin/archive/tags/Seattle/default.aspx">Seattle</category><category domain="http://weblogs.asp.net/dixin/archive/tags/Microsoft+Redmond+Campus/default.aspx">Microsoft Redmond Campus</category><category domain="http://weblogs.asp.net/dixin/archive/tags/Microsoft/default.aspx">Microsoft</category></item><item><title>Microsoft Most Valuable Professional Kit Unboxing</title><link>http://weblogs.asp.net/dixin/archive/2010/10/28/microsoft-most-valuable-professional-kit-unboxing.aspx</link><pubDate>Thu, 28 Oct 2010 00:54:09 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:7633445</guid><dc:creator>Dixin</dc:creator><slash:comments>16</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/dixin/rsscomments.aspx?PostID=7633445</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/dixin/commentapi.aspx?PostID=7633445</wfw:comment><comments>http://weblogs.asp.net/dixin/archive/2010/10/28/microsoft-most-valuable-professional-kit-unboxing.aspx#comments</comments><description>&lt;p&gt;I am very happy to receive the &lt;a href="http://mvp.support.microsoft.com/" target="_blank"&gt;Microsoft Most Valuable Professional&lt;/a&gt; Kit:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/dixin/Dixin-MVP.jpg" target="_blank"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="20101011115" border="0" alt="20101011115" src="http://weblogs.asp.net/blogs/dixin/20101011115_11AFD12A.jpg" width="640" height="472" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="20101011117" border="0" alt="20101011117" src="http://weblogs.asp.net/blogs/dixin/20101011117_448BC9E7.jpg" width="502" height="768" /&gt;&lt;/p&gt;  &lt;p&gt;The box is mailed from Redmond:&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_8621" border="0" alt="DSC_8621" src="http://weblogs.asp.net/blogs/dixin/DSC_8621_289A94EF.jpg" width="640" height="425" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_8623" border="0" alt="DSC_8623" src="http://weblogs.asp.net/blogs/dixin/DSC_8623_118C13B3.jpg" width="640" height="425" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_8624" border="0" alt="DSC_8624" src="http://weblogs.asp.net/blogs/dixin/DSC_8624_08BC0B67.jpg" width="510" height="768" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="DSC_8630" border="0" alt="DSC_8630" src="http://weblogs.asp.net/blogs/dixin/DSC_8630_2F41AC29.jpg" width="640" height="427" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_8632" border="0" alt="DSC_8632" src="http://weblogs.asp.net/blogs/dixin/DSC_8632_5B5A7596.jpg" width="640" height="425" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_8633" border="0" alt="DSC_8633" src="http://weblogs.asp.net/blogs/dixin/DSC_8633_4B6B30D2.jpg" width="640" height="425" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DSC_8676" border="0" alt="DSC_8676" src="http://weblogs.asp.net/blogs/dixin/DSC_8676_6099367A.jpg" width="640" height="425" /&gt;&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=7633445" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/dixin/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://weblogs.asp.net/dixin/archive/tags/Microsoft/default.aspx">Microsoft</category><category domain="http://weblogs.asp.net/dixin/archive/tags/C_2300_+3.0/default.aspx">C# 3.0</category><category domain="http://weblogs.asp.net/dixin/archive/tags/C_2300_+4.0/default.aspx">C# 4.0</category></item><item><title>Ellipses (…) In UI Command Text</title><link>http://weblogs.asp.net/dixin/archive/2010/06/27/ellipses-in-ui-command-text.aspx</link><pubDate>Sat, 26 Jun 2010 15:44:09 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:7544715</guid><dc:creator>Dixin</dc:creator><slash:comments>7</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/dixin/rsscomments.aspx?PostID=7544715</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/dixin/commentapi.aspx?PostID=7544715</wfw:comment><comments>http://weblogs.asp.net/dixin/archive/2010/06/27/ellipses-in-ui-command-text.aspx#comments</comments><description>&lt;p&gt;Some times, command text is followed by ellipsis (…) or not:&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; margin: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" class="wlDisabledImage" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/dixin/image_6AC3F6C5.png" width="316" height="267" /&gt;&lt;/p&gt;  &lt;p&gt;For years, many developers told me that ellipses mean a new window or dialog will pop up. For example, here:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Clicking New / Save / Exit will not pop up new window or dialog; &lt;/li&gt;    &lt;li&gt;Clicking Open… / Save As… / Page Setup… / Print… will pop up new window or dialog. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;But this is not correct. Take a look at About Notepad.&lt;/p&gt;  &lt;p&gt;Recently, someone argues about this old topic again. I think it is time to copy something from latest &lt;a href="http://www.microsoft.com/downloads/details.aspx?displaylang=en&amp;amp;FamilyID=e49820cb-954d-45ae-9cb3-1b9e8ea7fe8c" target="_blank"&gt;Windows User Experience Interaction Guidelines&lt;/a&gt;, and save to my blog. So next time when some other people are confused, I can just send a link to them.&lt;/p&gt;  &lt;p&gt;Page 10, Top Guidelines Violations:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;strong&gt;Ellipses mean incompleteness.&lt;/strong&gt; Use ellipses in UI text as follows:&lt;/p&gt;    &lt;ul&gt;     &lt;li&gt;&lt;strong&gt;Commands.&lt;/strong&gt; Indicate that a command needs additional information. Don’t use an ellipsis whenever an action displays another window—only when additional information is required. Commands whose implicit verb is to show another window don’t take an ellipsis, such as Advanced, Help, Options, Properties, or Settings.&lt;/li&gt;   &lt;/ul&gt; &lt;/blockquote&gt;  &lt;p&gt;Page 236, Menus:&lt;/p&gt;  &lt;blockquote&gt;   &lt;h3&gt;Using ellipses&lt;/h3&gt;    &lt;p&gt;While menu commands are used for immediate actions, more information might be needed to perform the action. &lt;strong&gt;Indicate a command that needs additional information (including a confirmation) by adding an ellipsis at the end of the label.&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; margin: 0px; display: inline; border-top: 0px; border-right: 0px" class="wlDisabledImage" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/dixin/image_7CC01485.png" width="738" height="432" /&gt;&lt;/p&gt;    &lt;p&gt;&lt;em&gt;In this example, the Print... command displays a Print dialog box to gather more information.&lt;/em&gt;&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;Proper use of ellipses is important to indicate that users can make further choices before performing the action, or even cancel the action entirely.&lt;/strong&gt; The visual cue offered by an ellipsis allows users to explore your software without fear.&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;This doesn’t mean you should use an ellipsis whenever an action displays another window&lt;/strong&gt;—only when additional information is required to perform the action. For example, the commands About, Advanced, Help, Options, Properties, and Settings must display another window when clicked, but don’t require additional information from the user. Therefore they don’t need ellipses.&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;In case of ambiguity (for example, the command label lacks a verb), decide based on the most likely user action.&lt;/strong&gt; If simply viewing the window is a common action, don’t use an ellipsis.&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;Correct:&lt;/strong&gt;       &lt;br /&gt;More colors...       &lt;br /&gt;Version information&lt;/p&gt;    &lt;p&gt;&lt;em&gt;In the first example, users are most likely going to choose a color, so using an ellipses is correct. In the second example, users are most likely going to view the version information, making ellipses unnecessary.&lt;/em&gt;&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; When determining if a menu command needs an ellipsis, don’t use the need to elevate privileges as a factor. Elevation isn’t information needed to perform a command (rather, it’s for permission) and the need to elevate is indicated with the security shield.      &lt;br /&gt;Labels&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;There are similar description in the other sections, like Buttons, Toolbars, etc. &lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=7544715" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/dixin/archive/tags/Windows/default.aspx">Windows</category><category domain="http://weblogs.asp.net/dixin/archive/tags/Usability/default.aspx">Usability</category></item><item><title>A Snapshot Of ASP.NET Homepage</title><link>http://weblogs.asp.net/dixin/archive/2010/06/11/a-snapshot-of-www-asp-net-homepage.aspx</link><pubDate>Thu, 10 Jun 2010 16:30:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:7524217</guid><dc:creator>Dixin</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/dixin/rsscomments.aspx?PostID=7524217</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/dixin/commentapi.aspx?PostID=7524217</wfw:comment><comments>http://weblogs.asp.net/dixin/archive/2010/06/11/a-snapshot-of-www-asp-net-homepage.aspx#comments</comments><description>&lt;P mce_keep="true"&gt;First time to appear on &lt;A href="http://www.asp.net/" target=_blank mce_href="http://www.asp.net"&gt;www.asp.net&lt;/A&gt;&amp;nbsp;homepage as headline!&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;A href="http://weblogs.asp.net/blogs/dixin/dixin-aspnet.png" target=_blank mce_href="http://weblogs.asp.net/blogs/dixin/dixin-aspnet.png"&gt;&lt;IMG style="WIDTH: 508px; HEIGHT: 665px" src="http://weblogs.asp.net/blogs/dixin/dixin-aspnet.png" width=508 height=665 mce_src="http://weblogs.asp.net/blogs/dixin/dixin-aspnet.png"&gt;&lt;/A&gt;&lt;/P&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=7524217" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/dixin/archive/tags/.NET/default.aspx">.NET</category><category domain="http://weblogs.asp.net/dixin/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://weblogs.asp.net/dixin/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://weblogs.asp.net/dixin/archive/tags/Web/default.aspx">Web</category><category domain="http://weblogs.asp.net/dixin/archive/tags/ASP.NET+MVC/default.aspx">ASP.NET MVC</category><category domain="http://weblogs.asp.net/dixin/archive/tags/AJAX/default.aspx">AJAX</category></item><item><title>A ToDynamic() Extension Method For Fluent Reflection</title><link>http://weblogs.asp.net/dixin/archive/2010/06/08/a-todynamic-extension-method-for-fluent-reflection.aspx</link><pubDate>Mon, 07 Jun 2010 15:19:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:7520430</guid><dc:creator>Dixin</dc:creator><slash:comments>13</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/dixin/rsscomments.aspx?PostID=7520430</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/dixin/commentapi.aspx?PostID=7520430</wfw:comment><comments>http://weblogs.asp.net/dixin/archive/2010/06/08/a-todynamic-extension-method-for-fluent-reflection.aspx#comments</comments><description>&lt;P&gt;Recently I needed to demonstrate some code with reflection, but I felt it inconvenient and tedious. To simplify the reflection coding, I created a ToDynamic() extension method. The source code can be downloaded from &lt;A href="http://weblogs.asp.net/blogs/dixin/DynamicWrapper.zip" target=_blank mce_href="http://weblogs.asp.net/blogs/dixin/DynamicWrapper.zip"&gt;here&lt;/A&gt;.&lt;/P&gt;
&lt;H1&gt;Problem&lt;/H1&gt;
&lt;P&gt;One example for complex reflection is in LINQ to SQL. The DataContext class has a property Privider, and this Provider has an Execute() method, which executes the query expression and returns the result. Assume this Execute() needs to be invoked to query SQL Server database, then the following code will be expected:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;using &lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;NorthwindDataContext &lt;/SPAN&gt;database = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;NorthwindDataContext&lt;/SPAN&gt;())
{
    &lt;SPAN style="COLOR: green"&gt;// Constructs the query.
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;IQueryable&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;Product&lt;/SPAN&gt;&amp;gt; query = database.Products.Where(product =&amp;gt; product.ProductID &amp;gt; 0)
                                                 .OrderBy(product =&amp;gt; product.ProductName)
                                                 .Take(2);

    &lt;SPAN style="COLOR: green"&gt;// Executes the query. Here reflection is required,
    // because Provider, Execute(), and ReturnValue are not public members. The following code cannot compile.
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;IEnumerable&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;Product&lt;/SPAN&gt;&amp;gt; results = database.&lt;U&gt;Provider&lt;/U&gt;.&lt;U&gt;Execute&lt;/U&gt;(query.Expression).&lt;U&gt;ReturnValue&lt;/U&gt;;

    &lt;SPAN style="COLOR: green"&gt;// Processes the results. &lt;/SPAN&gt;
    &lt;SPAN style="COLOR: blue"&gt;foreach &lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;Product &lt;/SPAN&gt;product &lt;SPAN style="COLOR: blue"&gt;in &lt;/SPAN&gt;results)
    {
        &lt;SPAN style="COLOR: #2b91af"&gt;Console&lt;/SPAN&gt;.WriteLine(&lt;SPAN style="COLOR: #a31515"&gt;"{0}, {1}"&lt;/SPAN&gt;, product.ProductID, product.ProductName);
    }
}&lt;/PRE&gt;
&lt;P&gt;Of course, this code cannot compile. And, no one wants to write code like this. Again, this is just an example of complex reflection.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;using &lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;NorthwindDataContext &lt;/SPAN&gt;database = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;NorthwindDataContext&lt;/SPAN&gt;())
{
    &lt;SPAN style="COLOR: green"&gt;// Constructs the query.
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;IQueryable&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;Product&lt;/SPAN&gt;&amp;gt; query = database.Products.Where(product =&amp;gt; product.ProductID &amp;gt; 0)
                                                 .OrderBy(product =&amp;gt; product.ProductName)
                                                 .Take(2);

    &lt;SPAN style="COLOR: green"&gt;// database.Provider
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;PropertyInfo &lt;/SPAN&gt;providerProperty = database.GetType().GetProperty(
        &lt;SPAN style="COLOR: #a31515"&gt;"Provider"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #2b91af"&gt;BindingFlags&lt;/SPAN&gt;.NonPublic | &lt;SPAN style="COLOR: #2b91af"&gt;BindingFlags&lt;/SPAN&gt;.GetProperty | &lt;SPAN style="COLOR: #2b91af"&gt;BindingFlags&lt;/SPAN&gt;.Instance);
    &lt;SPAN style="COLOR: blue"&gt;object &lt;/SPAN&gt;provider = providerProperty.GetValue(database, &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;);

    &lt;SPAN style="COLOR: green"&gt;// database.Provider.Execute(query.Expression)
    // Here GetMethod() cannot be directly used,
    // because Execute() is a explicitly implemented interface method.
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Assembly &lt;/SPAN&gt;assembly = &lt;SPAN style="COLOR: #2b91af"&gt;Assembly&lt;/SPAN&gt;.Load(&lt;SPAN style="COLOR: #a31515"&gt;"System.Data.Linq"&lt;/SPAN&gt;);
    &lt;SPAN style="COLOR: #2b91af"&gt;Type &lt;/SPAN&gt;providerType = assembly.GetTypes().SingleOrDefault(
        type =&amp;gt; type.FullName == &lt;SPAN style="COLOR: #a31515"&gt;"System.Data.Linq.Provider.IProvider"&lt;/SPAN&gt;);
    &lt;SPAN style="COLOR: #2b91af"&gt;InterfaceMapping &lt;/SPAN&gt;mapping = provider.GetType().GetInterfaceMap(providerType);
    &lt;SPAN style="COLOR: #2b91af"&gt;MethodInfo &lt;/SPAN&gt;executeMethod = mapping.InterfaceMethods.Single(method =&amp;gt; method.Name == &lt;SPAN style="COLOR: #a31515"&gt;"Execute"&lt;/SPAN&gt;);
    &lt;SPAN style="COLOR: #2b91af"&gt;IExecuteResult &lt;/SPAN&gt;executeResult = 
        executeMethod.Invoke(provider, &lt;SPAN style="COLOR: blue"&gt;new object&lt;/SPAN&gt;[] { query.Expression }) &lt;SPAN style="COLOR: blue"&gt;as &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;IExecuteResult&lt;/SPAN&gt;;

    &lt;SPAN style="COLOR: green"&gt;// database.Provider.Execute(query.Expression).ReturnValue
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;IEnumerable&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;Product&lt;/SPAN&gt;&amp;gt; results = executeResult.ReturnValue &lt;SPAN style="COLOR: blue"&gt;as &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;IEnumerable&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;Product&lt;/SPAN&gt;&amp;gt;;

    &lt;SPAN style="COLOR: green"&gt;// Processes the results.
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;foreach &lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;Product &lt;/SPAN&gt;product &lt;SPAN style="COLOR: blue"&gt;in &lt;/SPAN&gt;results)
    {
        &lt;SPAN style="COLOR: #2b91af"&gt;Console&lt;/SPAN&gt;.WriteLine(&lt;SPAN style="COLOR: #a31515"&gt;"{0}, {1}"&lt;/SPAN&gt;, product.ProductID, product.ProductName);
    }
}&lt;/PRE&gt;
&lt;P&gt;This may be not straight forward enough. So here is&amp;nbsp;a solution implementing fluent reflection with a ToDynamic() extension method:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: #2b91af"&gt;IEnumerable&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;Product&lt;/SPAN&gt;&amp;gt; results = database.&lt;U&gt;ToDynamic&lt;/U&gt;() &lt;SPAN style="COLOR: green"&gt;// Starts fluent reflection.&lt;/SPAN&gt; 
                                       .Provider.Execute(query.Expression).ReturnValue;&lt;/PRE&gt;
&lt;H1&gt;C# 4.0 dynamic&lt;/H1&gt;
&lt;P&gt;In this kind of scenarios, it is easy to have dynamic in mind, which enables developer to write whatever code after a dot:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;using &lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;NorthwindDataContext &lt;/SPAN&gt;database = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;NorthwindDataContext&lt;/SPAN&gt;())
{
    &lt;SPAN style="COLOR: green"&gt;// Constructs the query.
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;IQueryable&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;Product&lt;/SPAN&gt;&amp;gt; query = database.Products.Where(product =&amp;gt; product.ProductID &amp;gt; 0)
                                                 .OrderBy(product =&amp;gt; product.ProductName)
                                                 .Take(2);

    &lt;SPAN style="COLOR: green"&gt;// database.Provider
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;dynamic &lt;/SPAN&gt;dynamicDatabase = database;
    &lt;SPAN style="COLOR: blue"&gt;dynamic &lt;/SPAN&gt;results = dynamicDatabase.Provider.Execute(query).ReturnValue;
}&lt;/PRE&gt;
&lt;P&gt;This throws a RuntimeBinderException at runtime:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;'System.Data.Linq.DataContext.Provider' is inaccessible due to its protection level.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Here dynamic is able find the specified member. So the next thing is just writing some custom code to access the found member.&lt;/P&gt;
&lt;H1&gt;.NET 4.0 DynamicObject, and DynamicWrapper&amp;lt;T&amp;gt;&lt;/H1&gt;
&lt;P&gt;Where to put the custom code for dynamic? The answer is DynamicObject’s derived class. I first heard of DynamicObject from &lt;A href="http://channel9.msdn.com/pdc2008/TL16/" target=_blank mce_href="http://channel9.msdn.com/pdc2008/TL16/"&gt;Anders Hejlsberg's video in PDC2008&lt;/A&gt;. It is very powerful, providing useful virtual methods to be overridden, like:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;TryGetMember() &lt;/LI&gt;
&lt;LI&gt;TrySetMember() &lt;/LI&gt;
&lt;LI&gt;TryInvokeMember() &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;etc.&amp;nbsp; (In 2008 they are called GetMember, SetMember, etc., with different signature.)&lt;/P&gt;
&lt;P&gt;For example, if dynamicDatabase is a DynamicObject, then the following code:&lt;/P&gt;&lt;PRE class=code&gt;dynamicDatabase.Provider&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;will invoke dynamicDatabase.TryGetMember() to do the actual work, where custom code can be put into. &lt;/P&gt;
&lt;P&gt;Now create a type to inherit DynamicObject:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;public class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;DynamicWrapper&lt;/SPAN&gt;&amp;lt;T&amp;gt; : &lt;SPAN style="COLOR: #2b91af"&gt;DynamicObject
&lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: blue"&gt;private readonly bool &lt;/SPAN&gt;_isValueType;

    &lt;SPAN style="COLOR: blue"&gt;private readonly &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Type &lt;/SPAN&gt;_type;

    &lt;SPAN style="COLOR: blue"&gt;private &lt;/SPAN&gt;T _value; &lt;SPAN style="COLOR: green"&gt;// Not readonly, for value type scenarios.
&lt;/SPAN&gt;
    &lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;DynamicWrapper(&lt;SPAN style="COLOR: blue"&gt;ref &lt;/SPAN&gt;T value) &lt;SPAN style="COLOR: green"&gt;// Uses ref in case of value type.
    &lt;/SPAN&gt;{
        &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(value == &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;)
        {
            &lt;SPAN style="COLOR: blue"&gt;throw new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ArgumentNullException&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #a31515"&gt;"value"&lt;/SPAN&gt;);
        }

        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._value = value;
        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._type = value.GetType();
        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._isValueType = &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._type.IsValueType;
    }

    &lt;SPAN style="COLOR: blue"&gt;public override bool &lt;/SPAN&gt;TryGetMember(&lt;SPAN style="COLOR: #2b91af"&gt;GetMemberBinder &lt;/SPAN&gt;binder, &lt;SPAN style="COLOR: blue"&gt;out object &lt;/SPAN&gt;result)
    {
        &lt;SPAN style="COLOR: green"&gt;// Searches in current type's public and non-public properties.
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;PropertyInfo &lt;/SPAN&gt;property = &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._type.&lt;U&gt;GetTypeProperty&lt;/U&gt;(binder.Name);
        &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(property != &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;)
        {
            result = property.GetValue(&lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._value, &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;).&lt;U&gt;ToDynamic&lt;/U&gt;();
            &lt;SPAN style="COLOR: blue"&gt;return true&lt;/SPAN&gt;;
        }

        &lt;SPAN style="COLOR: green"&gt;// Searches in explicitly implemented properties for interface.
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;MethodInfo &lt;/SPAN&gt;method = &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._type.&lt;U&gt;GetInterfaceMethod&lt;/U&gt;(&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;.Concat(&lt;SPAN style="COLOR: #a31515"&gt;"get_"&lt;/SPAN&gt;, binder.Name), &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;);
        &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(method != &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;)
        {
            result = method.Invoke(&lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._value, &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;).&lt;U&gt;ToDynamic&lt;/U&gt;();
            &lt;SPAN style="COLOR: blue"&gt;return true&lt;/SPAN&gt;;
        }

        &lt;SPAN style="COLOR: green"&gt;// Searches in current type's public and non-public fields.
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;FieldInfo &lt;/SPAN&gt;field = &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._type.&lt;U&gt;GetTypeField&lt;/U&gt;(binder.Name);
        &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(field != &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;)
        {
            result = field.GetValue(&lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._value).&lt;U&gt;ToDynamic&lt;/U&gt;();
            &lt;SPAN style="COLOR: blue"&gt;return true&lt;/SPAN&gt;;
        }

        &lt;SPAN style="COLOR: green"&gt;// Searches in base type's public and non-public properties.
        &lt;/SPAN&gt;property = &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._type.&lt;U&gt;GetBaseProperty&lt;/U&gt;(binder.Name);
        &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(property != &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;)
        {
            result = property.GetValue(&lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._value, &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;).&lt;U&gt;ToDynamic&lt;/U&gt;();
            &lt;SPAN style="COLOR: blue"&gt;return true&lt;/SPAN&gt;;
        }

        &lt;SPAN style="COLOR: green"&gt;// Searches in base type's public and non-public fields.
        &lt;/SPAN&gt;field = &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._type.&lt;U&gt;GetBaseField&lt;/U&gt;(binder.Name);
        &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(field != &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;)
        {
            result = field.GetValue(&lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._value).&lt;U&gt;ToDynamic&lt;/U&gt;();
            &lt;SPAN style="COLOR: blue"&gt;return true&lt;/SPAN&gt;;
        }

        &lt;SPAN style="COLOR: green"&gt;// The specified member is not found.
        &lt;/SPAN&gt;result = &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;;
        &lt;SPAN style="COLOR: blue"&gt;return false&lt;/SPAN&gt;;
    }

    &lt;SPAN style="COLOR: green"&gt;// Other overridden methods are not listed.&lt;/SPAN&gt;
}&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;In the above code, GetTypeProperty(), GetInterfaceMethod(), GetTypeField(), GetBaseProperty(), and GetBaseField() are extension methods for Type class. For example:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;internal static class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;TypeExtensions
&lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: blue"&gt;internal static &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;FieldInfo &lt;/SPAN&gt;GetBaseField(&lt;SPAN style="COLOR: blue"&gt;this &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Type &lt;/SPAN&gt;type, &lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;name)
    {
        &lt;SPAN style="COLOR: #2b91af"&gt;Type &lt;/SPAN&gt;@base = type.BaseType;
        &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(@base == &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;)
        {
            &lt;SPAN style="COLOR: blue"&gt;return null&lt;/SPAN&gt;;
        }

        &lt;SPAN style="COLOR: blue"&gt;return &lt;/SPAN&gt;@base.GetTypeField(name) ?? @base.GetBaseField(name);
    }

    &lt;SPAN style="COLOR: blue"&gt;internal static &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;PropertyInfo &lt;/SPAN&gt;GetBaseProperty(&lt;SPAN style="COLOR: blue"&gt;this &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Type &lt;/SPAN&gt;type, &lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;name)
    {
        &lt;SPAN style="COLOR: #2b91af"&gt;Type &lt;/SPAN&gt;@base = type.BaseType;
        &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(@base == &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;)
        {
            &lt;SPAN style="COLOR: blue"&gt;return null&lt;/SPAN&gt;;
        }

        &lt;SPAN style="COLOR: blue"&gt;return &lt;/SPAN&gt;@base.GetTypeProperty(name) ?? @base.GetBaseProperty(name);
    }

    &lt;SPAN style="COLOR: blue"&gt;internal static &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;MethodInfo &lt;/SPAN&gt;GetInterfaceMethod(&lt;SPAN style="COLOR: blue"&gt;this &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Type &lt;/SPAN&gt;type, &lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;name, &lt;SPAN style="COLOR: blue"&gt;params object&lt;/SPAN&gt;[] args)
    {
        &lt;SPAN style="COLOR: blue"&gt;return
            &lt;/SPAN&gt;type.GetInterfaces().Select(type.GetInterfaceMap).SelectMany(mapping =&amp;gt; mapping.TargetMethods)
                .FirstOrDefault(
                    method =&amp;gt;
                    method.Name.Split(&lt;SPAN style="COLOR: #a31515"&gt;'.'&lt;/SPAN&gt;).Last().Equals(name, &lt;SPAN style="COLOR: #2b91af"&gt;StringComparison&lt;/SPAN&gt;.Ordinal) &amp;amp;&amp;amp;
                    method.GetParameters().Count() == args.Length &amp;amp;&amp;amp;
                    method.GetParameters().Select(
                        (parameter, index) =&amp;gt;
                        parameter.ParameterType.IsAssignableFrom(args[index].GetType())).Aggregate(
                            &lt;SPAN style="COLOR: blue"&gt;true&lt;/SPAN&gt;, (a, b) =&amp;gt; a &amp;amp;&amp;amp; b));
    }

    &lt;SPAN style="COLOR: blue"&gt;internal static &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;FieldInfo &lt;/SPAN&gt;GetTypeField(&lt;SPAN style="COLOR: blue"&gt;this &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Type &lt;/SPAN&gt;type, &lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;name)
    {
        &lt;SPAN style="COLOR: blue"&gt;return
            &lt;/SPAN&gt;type.GetFields(
                &lt;SPAN style="COLOR: #2b91af"&gt;BindingFlags&lt;/SPAN&gt;.GetField | &lt;SPAN style="COLOR: #2b91af"&gt;BindingFlags&lt;/SPAN&gt;.Instance | &lt;SPAN style="COLOR: #2b91af"&gt;BindingFlags&lt;/SPAN&gt;.Static | &lt;SPAN style="COLOR: #2b91af"&gt;BindingFlags&lt;/SPAN&gt;.Public |
                &lt;SPAN style="COLOR: #2b91af"&gt;BindingFlags&lt;/SPAN&gt;.NonPublic).FirstOrDefault(
                    field =&amp;gt; field.Name.Equals(name, &lt;SPAN style="COLOR: #2b91af"&gt;StringComparison&lt;/SPAN&gt;.Ordinal));
    }

    &lt;SPAN style="COLOR: blue"&gt;internal static &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;PropertyInfo &lt;/SPAN&gt;GetTypeProperty(&lt;SPAN style="COLOR: blue"&gt;this &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Type &lt;/SPAN&gt;type, &lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;name)
    {
        &lt;SPAN style="COLOR: blue"&gt;return
            &lt;/SPAN&gt;type.GetProperties(
                &lt;SPAN style="COLOR: #2b91af"&gt;BindingFlags&lt;/SPAN&gt;.GetProperty | &lt;SPAN style="COLOR: #2b91af"&gt;BindingFlags&lt;/SPAN&gt;.Instance | &lt;SPAN style="COLOR: #2b91af"&gt;BindingFlags&lt;/SPAN&gt;.Static |
                &lt;SPAN style="COLOR: #2b91af"&gt;BindingFlags&lt;/SPAN&gt;.Public | &lt;SPAN style="COLOR: #2b91af"&gt;BindingFlags&lt;/SPAN&gt;.NonPublic).FirstOrDefault(
                    property =&amp;gt; property.Name.Equals(name, &lt;SPAN style="COLOR: #2b91af"&gt;StringComparison&lt;/SPAN&gt;.Ordinal));
    }

    &lt;SPAN style="COLOR: green"&gt;// Other extension methods are not listed.
&lt;/SPAN&gt;}&lt;/PRE&gt;
&lt;P&gt;So now, when invoked, TryGetMember() searches the specified member and invoke it. The code can be written like this:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;dynamic &lt;/SPAN&gt;dynamicDatabase = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;DynamicWrapper&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;NorthwindDataContext&lt;/SPAN&gt;&amp;gt;(&lt;SPAN style="COLOR: blue"&gt;ref &lt;/SPAN&gt;database);
&lt;SPAN style="COLOR: blue"&gt;dynamic &lt;/SPAN&gt;dynamicReturnValue = dynamicDatabase.Provider.Execute(query.Expression).ReturnValue;&lt;/PRE&gt;
&lt;P&gt;This greatly simplified reflection.&lt;/P&gt;
&lt;H1&gt;ToDynamic() and fluent reflection&lt;/H1&gt;
&lt;P&gt;To make it even more straight forward, A ToDynamic() method is provided:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;public static class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;DynamicWrapperExtensions
&lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: blue"&gt;public static dynamic &lt;/SPAN&gt;ToDynamic&amp;lt;T&amp;gt;(&lt;SPAN style="COLOR: blue"&gt;this &lt;/SPAN&gt;T value)&lt;SPAN style="COLOR: green"&gt;
    &lt;/SPAN&gt;{
        &lt;SPAN style="COLOR: blue"&gt;return new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;DynamicWrapper&lt;/SPAN&gt;&amp;lt;T&amp;gt;(&lt;SPAN style="COLOR: blue"&gt;ref &lt;/SPAN&gt;value);
    }
}&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;and a ToStatic() method is provided to unwrap the value:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;public class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;DynamicWrapper&lt;/SPAN&gt;&amp;lt;T&amp;gt; : &lt;SPAN style="COLOR: #2b91af"&gt;DynamicObject
&lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;T ToStatic()
    {
        &lt;SPAN style="COLOR: blue"&gt;return this&lt;/SPAN&gt;._value;
    }&lt;SPAN style="COLOR: blue"&gt;
&lt;/SPAN&gt;}&lt;/PRE&gt;
&lt;P&gt;In the above TryGetMember() method, please notice it does not output the member’s value, but output a wrapped member value (that is, memberValue.ToDynamic()). This is very important to make the reflection fluent.&lt;/P&gt;
&lt;P&gt;Now the code becomes:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: #2b91af"&gt;IEnumerable&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;Product&lt;/SPAN&gt;&amp;gt; results = database.&lt;U&gt;ToDynamic&lt;/U&gt;() &lt;SPAN style="COLOR: green"&gt;// Here starts fluent reflection. &lt;/SPAN&gt;
                                       .Provider.Execute(query.Expression).ReturnValue
                                       .&lt;U&gt;ToStatic&lt;/U&gt;(); &lt;SPAN style="COLOR: green"&gt;// Unwraps to get the static value. &lt;/SPAN&gt;&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;With the help of TryConvert():&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;public class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;DynamicWrapper&lt;/SPAN&gt;&amp;lt;T&amp;gt; : &lt;SPAN style="COLOR: #2b91af"&gt;DynamicObject
&lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: blue"&gt;public override bool &lt;/SPAN&gt;TryConvert(&lt;SPAN style="COLOR: #2b91af"&gt;ConvertBinder &lt;/SPAN&gt;binder, &lt;SPAN style="COLOR: blue"&gt;out object &lt;/SPAN&gt;result)
    {
        result = &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._value;
        &lt;SPAN style="COLOR: blue"&gt;return true&lt;/SPAN&gt;;
    }
}&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;ToStatic() can be omitted:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: #2b91af"&gt;IEnumerable&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;Product&lt;/SPAN&gt;&amp;gt; results = database.&lt;U&gt;ToDynamic&lt;/U&gt;() 
                                       .Provider.Execute(query.Expression).ReturnValue;
                                       &lt;SPAN style="COLOR: green"&gt;// Automatically converts to expected static value.&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;Take a look at the reflection code at the beginning of this post again. Now it is much much simplified!&lt;/P&gt;
&lt;H1&gt;Special scenarios&lt;/H1&gt;
&lt;P&gt;In 90% of the scenarios &lt;U&gt;ToDynamic&lt;/U&gt;() is enough. But there are some special scenarios.&lt;/P&gt;
&lt;H2&gt;Access static members&lt;/H2&gt;
&lt;P&gt;Using extension method ToDynamic() for accessing static members does not make sense. Instead, DynamicWrapper&amp;lt;T&amp;gt; has a parameterless constructor to handle these scenarios:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;public class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;DynamicWrapper&lt;/SPAN&gt;&amp;lt;T&amp;gt; : &lt;SPAN style="COLOR: #2b91af"&gt;DynamicObject
&lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;DynamicWrapper() &lt;SPAN style="COLOR: green"&gt;// For static.
    &lt;/SPAN&gt;{
        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._type = &lt;SPAN style="COLOR: blue"&gt;typeof&lt;/SPAN&gt;(T);
        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._isValueType = &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._type.IsValueType;
    }&lt;SPAN style="COLOR: blue"&gt;
&lt;/SPAN&gt;}&lt;/PRE&gt;
&lt;P&gt;The reflection code should be like this:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;dynamic &lt;/SPAN&gt;wrapper = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;DynamicWrapper&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;StaticClass&lt;/SPAN&gt;&amp;gt;();
&lt;SPAN style="COLOR: blue"&gt;int &lt;/SPAN&gt;value = wrapper._value;
&lt;SPAN style="COLOR: blue"&gt;int &lt;/SPAN&gt;result = wrapper.PrivateMethod();&lt;/PRE&gt;
&lt;P&gt;So accessing static member is also simple, and fluent of course.&lt;/P&gt;
&lt;H2&gt;Change instances of value types&lt;/H2&gt;
&lt;P&gt;Value type is much more complex. The main problem is, value type is copied when passing to a method as a parameter. &lt;/P&gt;
&lt;P&gt;This is why ref keyword is used for the constructor. That is, if a value type instance is passed to DynamicWrapper&amp;lt;T&amp;gt;, the instance itself will be stored in this._value of DynamicWrapper&amp;lt;T&amp;gt;. Without the ref keyword, when this._value is changed, the value type instance itself does not change.&lt;/P&gt;
&lt;P&gt;Consider FieldInfo.SetValue(). In the value type scenarios, invoking FieldInfo.SetValue(this._value, value) does not change this._value, because it changes the copy of this._value.&lt;/P&gt;
&lt;P&gt;I searched the Web and found a solution for setting the value of field:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;internal static class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;FieldInfoExtensions
&lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: blue"&gt;internal static void &lt;/SPAN&gt;SetValue&amp;lt;T&amp;gt;(&lt;SPAN style="COLOR: blue"&gt;this &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;FieldInfo &lt;/SPAN&gt;field, &lt;SPAN style="COLOR: blue"&gt;ref &lt;/SPAN&gt;T obj, &lt;SPAN style="COLOR: blue"&gt;object &lt;/SPAN&gt;value)
    {
        &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;typeof&lt;/SPAN&gt;(T).IsValueType)
        {
            field.SetValueDirect(&lt;SPAN style="COLOR: blue"&gt;__makeref&lt;/SPAN&gt;(obj), value); &lt;SPAN style="COLOR: green"&gt;// For value type.&lt;/SPAN&gt; 
        }
        &lt;SPAN style="COLOR: blue"&gt;else
        &lt;/SPAN&gt;{
            field.SetValue(obj, value); &lt;SPAN style="COLOR: green"&gt;// For reference type.&lt;/SPAN&gt;
        }
    }&lt;SPAN style="COLOR: blue"&gt;
&lt;/SPAN&gt;}&lt;/PRE&gt;
&lt;P&gt;Here __makeref is a undocumented keyword of C#.&lt;/P&gt;
&lt;P&gt;But method invocation has problem. This is the source code of TryInvokeMember():&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;public override bool &lt;/SPAN&gt;TryInvokeMember(&lt;SPAN style="COLOR: #2b91af"&gt;InvokeMemberBinder &lt;/SPAN&gt;binder, &lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt;[] args, &lt;SPAN style="COLOR: blue"&gt;out object &lt;/SPAN&gt;result)
{
    &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(binder == &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;)
    {
        &lt;SPAN style="COLOR: blue"&gt;throw new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ArgumentNullException&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #a31515"&gt;"binder"&lt;/SPAN&gt;);
    }

    &lt;SPAN style="COLOR: #2b91af"&gt;MethodInfo &lt;/SPAN&gt;method = &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._type.GetTypeMethod(binder.Name, args) ??
                        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._type.GetInterfaceMethod(binder.Name, args) ??
                        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._type.GetBaseMethod(binder.Name, args);
    &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(method != &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;)
    {
        &lt;SPAN style="COLOR: green"&gt;// Oops!
        // If the returnValue is a struct, it is copied to heap.
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;object &lt;/SPAN&gt;resultValue = method.Invoke(&lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._value, args);
        &lt;SPAN style="COLOR: green"&gt;// And result is a wrapper of that copied struct.
        &lt;/SPAN&gt;result = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;DynamicWrapper&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt;&amp;gt;(&lt;SPAN style="COLOR: blue"&gt;ref &lt;/SPAN&gt;resultValue);
        &lt;SPAN style="COLOR: blue"&gt;return true&lt;/SPAN&gt;;
    }

    result = &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;;
    &lt;SPAN style="COLOR: blue"&gt;return false&lt;/SPAN&gt;;
}&lt;/PRE&gt;
&lt;P&gt;If the returned value is of value type, it will definitely copied, because MethodInfo.Invoke() does return object. If changing the value of the result, the copied struct is changed instead of the original struct. And so is the property and index accessing. They are both actually method invocation. For less confusion, setting property and index are not allowed on struct.&lt;/P&gt;
&lt;H1&gt;Conclusions&lt;/H1&gt;
&lt;P&gt;The DynamicWrapper&amp;lt;T&amp;gt; provides a simplified solution for reflection programming. It works for normal classes (reference types), accessing both instance and static members. &lt;/P&gt;
&lt;P&gt;In most of the scenarios, just remember to invoke ToDynamic() method, and access whatever you want:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: #2b91af"&gt;StaticType &lt;/SPAN&gt;result = someValue.&lt;U&gt;ToDynamic&lt;/U&gt;()._field.Method().Property[index];&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;In some special scenarios which requires changing the value of a struct (value type), this DynamicWrapper&amp;lt;T&amp;gt; does not work perfectly. Only changing struct’s field value is supported. &lt;/P&gt;
&lt;P&gt;The source code can be downloaded from &lt;A href="http://weblogs.asp.net/blogs/dixin/DynamicWrapper.zip" target=_blank mce_href="http://weblogs.asp.net/blogs/dixin/DynamicWrapper.zip"&gt;here&lt;/A&gt;, including a few unit test code.&lt;/P&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=7520430" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/dixin/archive/tags/.NET/default.aspx">.NET</category><category domain="http://weblogs.asp.net/dixin/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://weblogs.asp.net/dixin/archive/tags/C_2300_+4.0/default.aspx">C# 4.0</category><category domain="http://weblogs.asp.net/dixin/archive/tags/Dynamic/default.aspx">Dynamic</category></item><item><title>Back From Microsoft Web Camps Beijing</title><link>http://weblogs.asp.net/dixin/archive/2010/05/25/back-from-microsoft-web-camps-beijing.aspx</link><pubDate>Tue, 25 May 2010 01:12:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:7503441</guid><dc:creator>Dixin</dc:creator><slash:comments>9</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/dixin/rsscomments.aspx?PostID=7503441</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/dixin/commentapi.aspx?PostID=7503441</wfw:comment><comments>http://weblogs.asp.net/dixin/archive/2010/05/25/back-from-microsoft-web-camps-beijing.aspx#comments</comments><description>&lt;P&gt;I am just back from &lt;A href="http://www.webcamps.ms/" target=_blank mce_href="http://www.webcamps.ms/"&gt;Microsoft Web Camps&lt;/A&gt;, where Web developers in Beijing had a good time for 2 days with&amp;nbsp;2 fantastic speakers, &lt;A href="http://www.hanselman.com/" target=_blank mce_href="http://www.hanselman.com/"&gt;Scott Hanselman&lt;/A&gt; and &lt;A href="http://www.jamessenior.com/" target=_blank mce_href="http://www.jamessenior.com/"&gt;James Senior&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=webCamps_patch border=0 alt=webCamps_patch src="http://weblogs.asp.net/blogs/dixin/webCamps_patch_5743678F.png" width=240 height=232 mce_src="http://weblogs.asp.net/blogs/dixin/webCamps_patch_5743678F.png"&gt; &lt;/P&gt;
&lt;P&gt;On day 1, Scott and James talked about Web Platform Installer, ASP.NET core runtime, ASP.NET MVC, Entity Framework, Visual Studio 2010, … They were humorous and smart, and everyone was excited!&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=20100521009 border=0 alt=20100521009 src="http://weblogs.asp.net/blogs/dixin/20100521009_188E6A29.jpg" width=640 height=480 mce_src="http://weblogs.asp.net/blogs/dixin/20100521009_188E6A29.jpg"&gt; &lt;/P&gt;
&lt;P&gt;On day 2, developers were organized into teams to build Web applications. At the end of day 2, each team had a chance of presentation. Before ending, I also demonstrated my so-called&amp;nbsp;“&lt;A href="http://www.coolwebos.com/" target=_blank mce_href="http://www.coolwebos.com/"&gt;WebOS&lt;/A&gt;”, a tiny but funny Web website &lt;A href="http://weblogs.asp.net/dixin/archive/2009/09/20/introducing-coolwebos-com.aspx" target=_blank mce_href="http://weblogs.asp.net/dixin/archive/2009/09/20/introducing-coolwebos-com.aspx"&gt;developed with ASP.NET MVC and jQuery&lt;/A&gt;, which looks like an operating system, to show the power of ASP.NET MVC and jQuery. Scott, James and me were joking there, and people cannot help laughing and applauding…&lt;/P&gt;
&lt;P&gt;&lt;A href="http://www.coolwebos.com/" target=_blank mce_href="http://www.coolwebos.com/"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=image border=0 alt=image src="http://weblogs.asp.net/blogs/dixin/image_7BC4CF46.png" width=700 height=462 mce_src="http://weblogs.asp.net/blogs/dixin/image_7BC4CF46.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;&lt;A href="http://www.coolwebos.com/" target=_blank mce_href="http://www.coolwebos.com/"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=image border=0 alt=image src="http://weblogs.asp.net/blogs/dixin/image_219A3403.png" width=700 height=462 mce_src="http://weblogs.asp.net/blogs/dixin/image_219A3403.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;You can play with it here: &lt;A href="http://www.coolwebos.com/" target=_blank mce_href="http://www.coolwebos.com/"&gt;http://www.coolwebos.com/&lt;/A&gt;, if interested.&lt;/P&gt;
&lt;P&gt;I&amp;nbsp;discussed with Scott and James about Web and ASP.NET, like&amp;nbsp;some &lt;A href="http://weblogs.asp.net/dixin/archive/2010/05/22/anti-forgery-request-recipes-for-asp-net-mvc-and-ajax.aspx" target=_blank mce_href="http://weblogs.asp.net/dixin/archive/2010/05/22/anti-forgery-request-recipes-for-asp-net-mvc-and-ajax.aspx"&gt;junior ideas&lt;/A&gt; on ASP.NET MVC&amp;nbsp;anti-forgery request, etc. I also helped on some English / Chinese translation. At the end Scott gave me a fabulous gift, which I will post to blog later.&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://weblogs.asp.net/blogs/dixin/dixin-and-scott-hanselman.jpg" mce_src="http://weblogs.asp.net/blogs/dixin/dixin-and-scott-hanselman.jpg"&gt; &lt;IMG src="http://weblogs.asp.net/blogs/dixin/dixin-and-james-senior.jpg" mce_src="http://weblogs.asp.net/blogs/dixin/dixin-and-james-senior.jpg"&gt;&lt;/P&gt;
&lt;P&gt;Hope Microsoft can have more and more events like this!&lt;/P&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=7503441" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/dixin/archive/tags/.NET/default.aspx">.NET</category><category domain="http://weblogs.asp.net/dixin/archive/tags/jQuery/default.aspx">jQuery</category><category domain="http://weblogs.asp.net/dixin/archive/tags/Web/default.aspx">Web</category><category domain="http://weblogs.asp.net/dixin/archive/tags/ASP.NET+MVC/default.aspx">ASP.NET MVC</category><category domain="http://weblogs.asp.net/dixin/archive/tags/WebOS/default.aspx">WebOS</category><category domain="http://weblogs.asp.net/dixin/archive/tags/Microsoft/default.aspx">Microsoft</category></item><item><title>Anti-Forgery Request Recipes For ASP.NET MVC And AJAX</title><link>http://weblogs.asp.net/dixin/archive/2010/05/22/anti-forgery-request-recipes-for-asp-net-mvc-and-ajax.aspx</link><pubDate>Sat, 22 May 2010 08:34:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:7496795</guid><dc:creator>Dixin</dc:creator><slash:comments>37</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/dixin/rsscomments.aspx?PostID=7496795</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/dixin/commentapi.aspx?PostID=7496795</wfw:comment><comments>http://weblogs.asp.net/dixin/archive/2010/05/22/anti-forgery-request-recipes-for-asp-net-mvc-and-ajax.aspx#comments</comments><description>&lt;P&gt;This post discusses solutions for anti-forgery request scenarios in ASP.NET MVC and AJAX:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;How to enable validation on controller, instead of on each action;&lt;/LI&gt;
&lt;LI&gt;How to specify non-constant token salt in runtime;&lt;/LI&gt;
&lt;LI&gt;How to work with the server side validation in AJAX scenarios.&lt;/LI&gt;&lt;/UL&gt;
&lt;H1&gt;Background (Normal scenario of form submitting)&lt;/H1&gt;
&lt;P&gt;To secure websites from &lt;A href="http://en.wikipedia.org/wiki/Cross-site_request_forgery" target=_blank mce_href="http://en.wikipedia.org/wiki/Cross-site_request_forgery"&gt;cross-site request forgery&lt;/A&gt; (CSRF, or XSRF) attack, ASP.NET MVC provides an excellent mechanism:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;The server prints tokens to cookie and inside the form; &lt;/LI&gt;
&lt;LI&gt;When the form is submitted to server, token in cookie and token inside the form are sent in the HTTP request; &lt;/LI&gt;
&lt;LI&gt;Server validates the tokens. &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;To print tokens to browser, just invoke HtmlHelper.AntiForgeryToken():&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="BACKGROUND: yellow"&gt;&amp;lt;%&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;using &lt;/SPAN&gt;(Html.BeginForm())
   { &lt;SPAN style="BACKGROUND: yellow"&gt;%&amp;gt;
&lt;/SPAN&gt;    &lt;SPAN style="BACKGROUND: yellow"&gt;&amp;lt;%&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;: this&lt;/SPAN&gt;.Html.AntiForgeryToken(&lt;SPAN style="COLOR: #2b91af"&gt;Constants&lt;/SPAN&gt;.AntiForgeryTokenSalt)&lt;SPAN style="BACKGROUND: yellow"&gt;%&amp;gt;

&lt;/SPAN&gt;    &lt;SPAN style="BACKGROUND: yellow"&gt;&amp;lt;%&lt;/SPAN&gt;&lt;SPAN style="COLOR: #006400"&gt;-- Other fields. --&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: yellow"&gt;%&amp;gt;

&lt;/SPAN&gt;    &lt;SPAN style="COLOR: blue"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;input &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;type&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="submit" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;value&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Submit" /&amp;gt;
&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: yellow"&gt;&amp;lt;%&lt;/SPAN&gt; } &lt;SPAN style="BACKGROUND: yellow"&gt;%&amp;gt;
&lt;/SPAN&gt;&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;This invocation generates a token&amp;nbsp;and writes it&amp;nbsp;inside the form:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;form &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;action&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="..." &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;method&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="post"&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;input &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="__RequestVerificationToken" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;type&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="hidden" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;value&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="J56khgCvbE3bVcsCSZkNVuH9Cclm9SSIT/ywruFsXEgmV8CL2eW5C/gGsQUf/YuP" /&amp;gt;
 
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #006400"&gt;&amp;lt;!-- Other fields. --&amp;gt;
 
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;input &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;type&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="submit" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;value&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Submit" /&amp;gt;
&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;form&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
&lt;/SPAN&gt;&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;and also writes it&amp;nbsp;into the cookie:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;CODE&gt;__RequestVerificationToken_Lw__= &lt;BR&gt;J56khgCvbE3bVcsCSZkNVuH9Cclm9SSIT/ywruFsXEgmV8CL2eW5C/gGsQUf/YuP&lt;/CODE&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;When the above form is submitted, they are both sent to server. &lt;/P&gt;
&lt;P&gt;In the server side, [ValidateAntiForgeryToken] attribute is used to specify the controllers or actions to validate them:&lt;/P&gt;&lt;PRE class=code&gt;[&lt;SPAN style="COLOR: #2b91af"&gt;HttpPost&lt;/SPAN&gt;]
[&lt;SPAN style="COLOR: #2b91af"&gt;ValidateAntiForgeryToken&lt;/SPAN&gt;(Salt = &lt;SPAN style="COLOR: #2b91af"&gt;Constants&lt;/SPAN&gt;.AntiForgeryTokenSalt)]
&lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ActionResult &lt;/SPAN&gt;Action(&lt;SPAN style="COLOR: green"&gt;/* ... */&lt;/SPAN&gt;)
{
    &lt;SPAN style="COLOR: green"&gt;// ...
&lt;/SPAN&gt;}&lt;/PRE&gt;
&lt;P&gt;This is very productive for &lt;U&gt;form scenarios&lt;/U&gt;. But recently, when resolving security vulnerabilities for Web products, problems are encountered.&lt;/P&gt;
&lt;H1&gt;Turn on validation on controller (not on each action)&lt;/H1&gt;
&lt;P&gt;The server side problem is, one single [ValidateAntiForgeryToken] attribute is expected to declare on controller, but actually a lot of attributes have be to declared on controller's each POST actions. Because POST actions are usually much more then controllers, the work would be a little crazy.&lt;/P&gt;
&lt;H2&gt;Problem&lt;/H2&gt;
&lt;P&gt;Usually a controller contains both actions for HTTP GET requests and actions for POST, and, usually validations are expected for only HTTP POST requests. So, if the [ValidateAntiForgeryToken] is declared on the controller, &lt;U&gt;the HTTP GET requests become invalid&lt;/U&gt;:&lt;/P&gt;&lt;PRE class=code&gt;[&lt;SPAN style="COLOR: #2b91af"&gt;&lt;U&gt;ValidateAntiForgeryToken&lt;/U&gt;&lt;/SPAN&gt;(Salt = &lt;SPAN style="COLOR: #2b91af"&gt;Constants&lt;/SPAN&gt;.AntiForgeryTokenSalt)]
&lt;SPAN style="COLOR: blue"&gt;public class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ProductController &lt;/SPAN&gt;: &lt;SPAN style="COLOR: #2b91af"&gt;Controller &lt;SPAN style="COLOR: #006400"&gt;// One [ValidateAntiForgeryToken] attribute.&lt;/SPAN&gt; 
&lt;/SPAN&gt;{
    [&lt;SPAN style="COLOR: #2b91af"&gt;HttpGet&lt;/SPAN&gt;]
    &lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ActionResult &lt;/SPAN&gt;Index() &lt;SPAN style="COLOR: green"&gt;// Index() cannot work.
    &lt;/SPAN&gt;{
        &lt;SPAN style="COLOR: green"&gt;// ...
    &lt;/SPAN&gt;}

    [&lt;SPAN style="COLOR: #2b91af"&gt;HttpPost&lt;/SPAN&gt;]
    &lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ActionResult &lt;/SPAN&gt;PostAction1(&lt;SPAN style="COLOR: green"&gt;/* ... */&lt;/SPAN&gt;)
    { 
        &lt;SPAN style="COLOR: green"&gt;// ...
    &lt;/SPAN&gt;}

    [&lt;SPAN style="COLOR: #2b91af"&gt;HttpPost&lt;/SPAN&gt;]
    &lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ActionResult &lt;/SPAN&gt;PostAction2(&lt;SPAN style="COLOR: green"&gt;/* ... */&lt;/SPAN&gt;)
    {
        &lt;SPAN style="COLOR: green"&gt;// ...
    &lt;/SPAN&gt;}

    &lt;SPAN style="COLOR: green"&gt;// Other actions.
&lt;/SPAN&gt;}&lt;/PRE&gt;
&lt;P&gt;If browser sends an HTTP GET request by clicking a link: http://Site/Product/Index, validation definitely fails, because no token is provided (by http://Site/Product/Index?__RequestVerificationToken=???, for example). &lt;/P&gt;
&lt;P&gt;As a result, many [ValidateAntiForgeryToken] attributes have be distributed to each POST action:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;public class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ProductController &lt;/SPAN&gt;: &lt;SPAN style="COLOR: #2b91af"&gt;Controller &lt;SPAN style="COLOR: #006400"&gt;// Many [ValidateAntiForgeryToken] attributes.&lt;/SPAN&gt;
&lt;/SPAN&gt;{
    [&lt;SPAN style="COLOR: #2b91af"&gt;HttpGet&lt;/SPAN&gt;]
    &lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ActionResult &lt;/SPAN&gt;Index() &lt;SPAN style="COLOR: green"&gt;// Works.
    &lt;/SPAN&gt;{
        &lt;SPAN style="COLOR: green"&gt;// ...
    &lt;/SPAN&gt;}

    [&lt;SPAN style="COLOR: #2b91af"&gt;HttpPost&lt;/SPAN&gt;]
    [&lt;SPAN style="COLOR: #2b91af"&gt;&lt;U&gt;ValidateAntiForgeryToken&lt;/U&gt;&lt;/SPAN&gt;(Salt = &lt;SPAN style="COLOR: #2b91af"&gt;Constants&lt;/SPAN&gt;.AntiForgeryTokenSalt)]
    &lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ActionResult &lt;/SPAN&gt;PostAction1(&lt;SPAN style="COLOR: green"&gt;/* ... */&lt;/SPAN&gt;)
    { 
        &lt;SPAN style="COLOR: green"&gt;// ...
    &lt;/SPAN&gt;}

    [&lt;SPAN style="COLOR: #2b91af"&gt;HttpPost&lt;/SPAN&gt;]
    [&lt;SPAN style="COLOR: #2b91af"&gt;&lt;U&gt;ValidateAntiForgeryToken&lt;/U&gt;&lt;/SPAN&gt;(Salt = &lt;SPAN style="COLOR: #2b91af"&gt;Constants&lt;/SPAN&gt;.AntiForgeryTokenSalt)]
    &lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ActionResult &lt;/SPAN&gt;PostAction2(&lt;SPAN style="COLOR: green"&gt;/* ... */&lt;/SPAN&gt;)
    {
        &lt;SPAN style="COLOR: green"&gt;// ...
    &lt;/SPAN&gt;}

    &lt;SPAN style="COLOR: green"&gt;// Other actions.
&lt;/SPAN&gt;}&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;This would be a little bit crazy, because one Web product can have a lot of POST actions.&lt;/P&gt;
&lt;H2&gt;Solution&lt;/H2&gt;
&lt;P&gt;To avoid a large number of [ValidateAntiForgeryToken] attributes (one for each POST action), the following ValidateAntiForgeryTokenWrapperAttribute wrapper class can be helpful, where HTTP verbs can be specified:&lt;/P&gt;&lt;PRE class=code&gt;[&lt;SPAN style="COLOR: #2b91af"&gt;AttributeUsage&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;AttributeTargets&lt;/SPAN&gt;.Class | &lt;SPAN style="COLOR: #2b91af"&gt;AttributeTargets&lt;/SPAN&gt;.Method,
    AllowMultiple = &lt;SPAN style="COLOR: blue"&gt;false&lt;/SPAN&gt;, Inherited = &lt;SPAN style="COLOR: blue"&gt;true&lt;/SPAN&gt;)]
&lt;SPAN style="COLOR: blue"&gt;public class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ValidateAntiForgeryTokenWrapperAttribute &lt;/SPAN&gt;: &lt;SPAN style="COLOR: #2b91af"&gt;FilterAttribute&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #2b91af"&gt;IAuthorizationFilter
&lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: blue"&gt;private readonly &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ValidateAntiForgeryTokenAttribute &lt;/SPAN&gt;_validator;

    &lt;SPAN style="COLOR: blue"&gt;private readonly &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;AcceptVerbsAttribute &lt;/SPAN&gt;_verbs;

    &lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;ValidateAntiForgeryTokenWrapperAttribute(&lt;SPAN style="COLOR: #2b91af"&gt;HttpVerbs &lt;/SPAN&gt;verbs)
        : &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;(verbs, &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;)
    {
    }

    &lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;ValidateAntiForgeryTokenWrapperAttribute(&lt;SPAN style="COLOR: #2b91af"&gt;HttpVerbs &lt;/SPAN&gt;verbs, &lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;salt)
    {
        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._verbs = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;AcceptVerbsAttribute&lt;/SPAN&gt;(verbs);
        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._validator = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ValidateAntiForgeryTokenAttribute&lt;/SPAN&gt;()
            {
                Salt = salt
            };
    }

    &lt;SPAN style="COLOR: blue"&gt;public void &lt;/SPAN&gt;OnAuthorization(&lt;SPAN style="COLOR: #2b91af"&gt;AuthorizationContext &lt;/SPAN&gt;filterContext)
    {
        &lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;httpMethodOverride = filterContext.HttpContext.Request.GetHttpMethodOverride();
        &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._verbs.Verbs.Contains(httpMethodOverride, &lt;SPAN style="COLOR: #2b91af"&gt;StringComparer&lt;/SPAN&gt;.OrdinalIgnoreCase))
        {
            &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._validator.OnAuthorization(filterContext);
        }
    }
}&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;Here only HTTP requests of the specified verbs are validated:&lt;/P&gt;&lt;PRE class=code&gt;[&lt;SPAN style="COLOR: #2b91af"&gt;ValidateAntiForgeryTokenWrapper&lt;/SPAN&gt;(&lt;U&gt;&lt;SPAN style="COLOR: #2b91af"&gt;HttpVerbs&lt;/SPAN&gt;.Post&lt;/U&gt;, &lt;SPAN style="COLOR: #2b91af"&gt;Constants&lt;/SPAN&gt;.AntiForgeryTokenSalt)]
&lt;SPAN style="COLOR: blue"&gt;public class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ProductController &lt;/SPAN&gt;: &lt;SPAN style="COLOR: #2b91af"&gt;Controller
&lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: green"&gt;// GET actions are not affected.
    // Only HTTP POST requests are validated.
&lt;/SPAN&gt;}&lt;/PRE&gt;
&lt;P&gt;Now &lt;U&gt;one single attribute on a controller&lt;/U&gt; turns on validation for all POST actions in that controller.&lt;/P&gt;
&lt;P&gt;It would be nice if HTTP verbs can be specified on the built-in [ValidateAntiForgeryToken] attribute. And, this is very easy to implement.&lt;/P&gt;
&lt;H1&gt;Specify non-constant salt in runtime&lt;/H1&gt;
&lt;P&gt;By default, the salt should be a compile time constant, so it can be used for the [ValidateAntiForgeryToken] or [ValidateAntiForgeryTokenWrapper] attribute.&lt;/P&gt;
&lt;H2&gt;Problem&lt;/H2&gt;
&lt;P&gt;One Web product might be sold to many clients. If a constant salt is evaluated in compile time, after the product is built and deployed to many clients, they all have the same salt. Of course, clients do not like this. Even some clients might expect a configurable custom salt. In these scenarios, salt is required to be a runtime value.&lt;/P&gt;
&lt;H2&gt;Solution&lt;/H2&gt;
&lt;P&gt;In the above [ValidateAntiForgeryToken] and [ValidateAntiForgeryTokenWrapper] attributes, the salt is passed through constructor. So one solution is to remove that parameter:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;public class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ValidateAntiForgeryTokenWrapperAttribute &lt;/SPAN&gt;: &lt;SPAN style="COLOR: #2b91af"&gt;FilterAttribute&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #2b91af"&gt;IAuthorizationFilter
&lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;ValidateAntiForgeryTokenWrapperAttribute(&lt;SPAN style="COLOR: #2b91af"&gt;HttpVerbs &lt;/SPAN&gt;verbs)
    {
        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._verbs = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;AcceptVerbsAttribute&lt;/SPAN&gt;(verbs);
        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._validator = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ValidateAntiForgeryTokenAttribute&lt;/SPAN&gt;()
            {
                Salt = &lt;U&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Configurations&lt;/SPAN&gt;.AntiForgeryTokenSalt&lt;/U&gt;
            };
    }

    &lt;SPAN style="COLOR: green"&gt;// Other members.
&lt;/SPAN&gt;}&lt;/PRE&gt;
&lt;P&gt;But this smells bad because the injected dependency becomes a hard dependency. So the other solution to work around the limitation of attributes, is moving validation code into controller:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;public abstract class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;AntiForgeryControllerBase &lt;/SPAN&gt;: &lt;SPAN style="COLOR: #2b91af"&gt;Controller
&lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: blue"&gt;private readonly &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ValidateAntiForgeryTokenAttribute &lt;/SPAN&gt;_validator;

    &lt;SPAN style="COLOR: blue"&gt;private readonly &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;AcceptVerbsAttribute &lt;/SPAN&gt;_verbs;

    &lt;SPAN style="COLOR: blue"&gt;protected &lt;/SPAN&gt;AntiForgeryControllerBase(&lt;SPAN style="COLOR: #2b91af"&gt;HttpVerbs &lt;/SPAN&gt;verbs, &lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;salt)
    {
        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._verbs = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;AcceptVerbsAttribute&lt;/SPAN&gt;(verbs);
        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._validator = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ValidateAntiForgeryTokenAttribute&lt;/SPAN&gt;()
            {
                Salt = salt
            };
    }

    &lt;SPAN style="COLOR: blue"&gt;protected override void &lt;/SPAN&gt;OnAuthorization(&lt;SPAN style="COLOR: #2b91af"&gt;AuthorizationContext &lt;/SPAN&gt;filterContext)
    {
        &lt;SPAN style="COLOR: blue"&gt;base&lt;/SPAN&gt;.OnAuthorization(filterContext);

        &lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;httpMethodOverride = filterContext.HttpContext.Request.GetHttpMethodOverride();
        &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._verbs.Verbs.Contains(httpMethodOverride, &lt;SPAN style="COLOR: #2b91af"&gt;StringComparer&lt;/SPAN&gt;.OrdinalIgnoreCase))
        {
            &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._validator.OnAuthorization(filterContext);
        }
    }
}&lt;/PRE&gt;
&lt;P&gt;Then just make controller classes inheriting from this AntiForgeryControllerBase class. Now the salt is no long required to be a compile time constant.&lt;/P&gt;
&lt;H1&gt;Submit token via AJAX&lt;/H1&gt;
&lt;P&gt;For browser side, once server side turns on anti-forgery validation for HTTP POST, all AJAX POST requests will fail by default.&lt;/P&gt;
&lt;H2&gt;Problem&lt;/H2&gt;
&lt;P&gt;In &lt;U&gt;AJAX scenarios&lt;/U&gt;, the HTTP POST request is not sent by form. Take jQuery as an example:&lt;/P&gt;&lt;PRE class=code&gt;$.post(url, {
    productName: &lt;SPAN style="COLOR: maroon"&gt;"Tofu"&lt;/SPAN&gt;,
    categoryId: 1 &lt;SPAN style="COLOR: #006400"&gt;// Token is not posted.
&lt;/SPAN&gt;}, callback);&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;&lt;U&gt;This kind of AJAX POST requests will always be invalid&lt;/U&gt;, because server side code cannot see the token in the posted data.&lt;/P&gt;
&lt;H2&gt;Solution&lt;/H2&gt;
&lt;P&gt;Basically, the tokens must be printed to browser then sent back to server. So first of all, HtmlHelper.AntiForgeryToken() need to be called somewhere. Now the browser has token in both HTML and cookie.&lt;/P&gt;
&lt;P&gt;Then jQuery must find the printed token in the HTML, and append token to the data before sending:&lt;/P&gt;&lt;PRE class=code&gt;$.post(url, {
    productName: &lt;SPAN style="COLOR: maroon"&gt;"Tofu"&lt;/SPAN&gt;,
    categoryId: 1,
    __RequestVerificationToken: getToken() &lt;SPAN style="COLOR: #006400"&gt;// Token is posted.
&lt;/SPAN&gt;}, callback);&lt;/PRE&gt;
&lt;P&gt;To be reusable, this can be encapsulated into a tiny jQuery plugin:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: #006400"&gt;/// &amp;lt;reference path="jquery-1.4.2.js" /&amp;gt;

&lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;function &lt;/SPAN&gt;($) {
    $.getAntiForgeryToken = &lt;SPAN style="COLOR: blue"&gt;function &lt;/SPAN&gt;(tokenWindow, appPath) {
        &lt;SPAN style="COLOR: #006400"&gt;// HtmlHelper.AntiForgeryToken() must be invoked to print the token.
        &lt;/SPAN&gt;tokenWindow = tokenWindow &amp;amp;&amp;amp; &lt;SPAN style="COLOR: blue"&gt;typeof &lt;/SPAN&gt;tokenWindow === &lt;SPAN style="COLOR: blue"&gt;typeof &lt;/SPAN&gt;window ? tokenWindow : window;

        appPath = appPath &amp;amp;&amp;amp; &lt;SPAN style="COLOR: blue"&gt;typeof &lt;/SPAN&gt;appPath === &lt;SPAN style="COLOR: maroon"&gt;"string" &lt;/SPAN&gt;? &lt;SPAN style="COLOR: maroon"&gt;"_" &lt;/SPAN&gt;+ appPath.toString() : &lt;SPAN style="COLOR: maroon"&gt;""&lt;/SPAN&gt;;
        &lt;SPAN style="COLOR: #006400"&gt;// The name attribute is either __RequestVerificationToken,
        // or __RequestVerificationToken_{appPath}.
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;tokenName = &lt;SPAN style="COLOR: maroon"&gt;"__RequestVerificationToken" &lt;/SPAN&gt;+ appPath;

        &lt;SPAN style="COLOR: #006400"&gt;// Finds the &amp;lt;input type="hidden" name={tokenName} value="..." /&amp;gt; from the specified window.
        // var inputElements = tokenWindow.$("input[type='hidden'][name=' + tokenName + "']");
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;inputElements = tokenWindow.document.getElementsByTagName(&lt;SPAN style="COLOR: maroon"&gt;"input"&lt;/SPAN&gt;);
        &lt;SPAN style="COLOR: blue"&gt;for &lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;i = 0; i &amp;lt; inputElements.length; i++) {
            &lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;inputElement = inputElements[i];
            &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(inputElement.type === &lt;SPAN style="COLOR: maroon"&gt;"hidden" &lt;/SPAN&gt;&amp;amp;&amp;amp; inputElement.name === tokenName) {
                &lt;SPAN style="COLOR: blue"&gt;return &lt;/SPAN&gt;{
                    name: tokenName,
                    value: inputElement.value
                };
            }
        }
    };

    $.appendAntiForgeryToken = &lt;SPAN style="COLOR: blue"&gt;function &lt;/SPAN&gt;(data, token) {
        &lt;SPAN style="COLOR: #006400"&gt;// Converts data if not already a string.
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(data &amp;amp;&amp;amp; &lt;SPAN style="COLOR: blue"&gt;typeof &lt;/SPAN&gt;data !== &lt;SPAN style="COLOR: maroon"&gt;"string"&lt;/SPAN&gt;) {
            data = $.param(data);
        }

        &lt;SPAN style="COLOR: #006400"&gt;// Gets token from current window by default.
        &lt;/SPAN&gt;token = token ? token : $.getAntiForgeryToken(); &lt;SPAN style="COLOR: #006400"&gt;// $.getAntiForgeryToken(window).

        &lt;/SPAN&gt;data = data ? data + &lt;SPAN style="COLOR: maroon"&gt;"&amp;amp;" &lt;/SPAN&gt;: &lt;SPAN style="COLOR: maroon"&gt;""&lt;/SPAN&gt;;
        &lt;SPAN style="COLOR: #006400"&gt;// If token exists, appends {token.name}={token.value} to data.
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;return &lt;/SPAN&gt;token ? data + encodeURIComponent(token.name) + &lt;SPAN style="COLOR: maroon"&gt;"=" &lt;/SPAN&gt;+ encodeURIComponent(token.value) : data;
    };

    &lt;SPAN style="COLOR: #006400"&gt;// Wraps $.post(url, data, callback, type) for most common scenarios.
    &lt;/SPAN&gt;$.postAntiForgery = &lt;SPAN style="COLOR: blue"&gt;function &lt;/SPAN&gt;(url, data, callback, type) {
        &lt;SPAN style="COLOR: blue"&gt;return &lt;/SPAN&gt;$.post(url, $.appendAntiForgeryToken(data), callback, type);
    };

    &lt;SPAN style="COLOR: #006400"&gt;// Wraps $.ajax(settings).
    &lt;/SPAN&gt;$.ajaxAntiForgery = &lt;SPAN style="COLOR: blue"&gt;function &lt;/SPAN&gt;(settings) {
        &lt;SPAN style="COLOR: #006400"&gt;// Supports more options than $.ajax(): 
        // settings.token, settings.tokenWindow, settings.appPath.
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;token = settings.token ? settings.token : $.getAntiForgeryToken(settings.tokenWindow, settings.appPath);
        settings.data = $.appendAntiForgeryToken(settings.data, token);
        &lt;SPAN style="COLOR: blue"&gt;return &lt;/SPAN&gt;$.ajax(settings);
    };
})(jQuery);&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;In most of the scenarios, it is Ok to just replace $.post() invocation with $.&lt;U&gt;postAntiForgery&lt;/U&gt;(), and replace $.ajax() with $.&lt;U&gt;ajaxAntiForgery&lt;/U&gt;():&lt;/P&gt;&lt;PRE class=code&gt;$.&lt;U&gt;postAntiForgery&lt;/U&gt;(url, {
    productName: &lt;SPAN style="COLOR: maroon"&gt;"Tofu"&lt;/SPAN&gt;,
    categoryId: 1
}, callback); &lt;SPAN style="COLOR: #006400"&gt;// The same usage as $.post(), but token is posted. &lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;There might be some scenarios of custom token, where $.&lt;U&gt;appendAntiForgeryToken&lt;/U&gt;() is useful:&lt;/P&gt;&lt;PRE class=code&gt;data = $.appendAntiForgeryToken(data, &lt;U&gt;token&lt;/U&gt;);
&lt;SPAN style="COLOR: #006400"&gt;// Token is already in data. No need to invoke $.postAntiForgery().
&lt;/SPAN&gt;$.post(url, data, callback);&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;or $.&lt;U&gt;ajaxAntiForgery&lt;/U&gt;() can be used:&lt;/P&gt;&lt;PRE class=code&gt;$.ajaxAntiForgery({
    type: &lt;SPAN style="COLOR: maroon"&gt;"POST"&lt;/SPAN&gt;,
    url: url,
    data: {
        productName: &lt;SPAN style="COLOR: maroon"&gt;"Tofu"&lt;/SPAN&gt;,
        categoryId: 1
    },
    success: callback, &lt;SPAN style="COLOR: #006400"&gt;// The same usage as $.ajax(), supporting more options.
    &lt;/SPAN&gt;&lt;U&gt;token&lt;/U&gt;: token &lt;SPAN style="COLOR: #006400"&gt;// Custom token.
&lt;/SPAN&gt;});&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;And there are special scenarios that the token is not in the current window. For example:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;An HTTP POST request can be sent from an iframe, while the token is in the parent window or top window;&lt;/LI&gt;
&lt;LI&gt;An HTTP POST request can be sent from an popup window or a dialog, while the token is in the opener window;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;etc. Here, token's container window can be specified for $.&lt;U&gt;getAntiForgeryToken&lt;/U&gt;():&lt;/P&gt;&lt;PRE class=code&gt;data = $.appendAntiForgeryToken(data, $.getAntiForgeryToken(&lt;U&gt;window.parent&lt;/U&gt;));
&lt;SPAN style="COLOR: #006400"&gt;// Token is already in data. No need to invoke $.postAntiForgery().
&lt;/SPAN&gt;$.post(url, data, callback);&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;or $.&lt;U&gt;ajaxAntiForgery&lt;/U&gt;() can be used:&lt;/P&gt;&lt;PRE class=code&gt;$.ajaxAntiForgery({
    type: &lt;SPAN style="COLOR: maroon"&gt;"POST"&lt;/SPAN&gt;,
    url: url,
    data: {
        productName: &lt;SPAN style="COLOR: maroon"&gt;"Tofu"&lt;/SPAN&gt;,
        categoryId: 1
    },
    success: callback, &lt;SPAN style="COLOR: #006400"&gt;// The same usage as $.ajax(), supporting more options.
    &lt;/SPAN&gt;&lt;U&gt;tokenWindow&lt;/U&gt;: window.parent &lt;SPAN style="COLOR: #006400"&gt;// Token is in another window.
&lt;/SPAN&gt;});&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;If you have better solution, please do tell me.&lt;/P&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=7496795" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/dixin/archive/tags/.NET/default.aspx">.NET</category><category domain="http://weblogs.asp.net/dixin/archive/tags/JavaScript/default.aspx">JavaScript</category><category domain="http://weblogs.asp.net/dixin/archive/tags/jQuery/default.aspx">jQuery</category><category domain="http://weblogs.asp.net/dixin/archive/tags/Web/default.aspx">Web</category><category domain="http://weblogs.asp.net/dixin/archive/tags/ASP.NET+MVC/default.aspx">ASP.NET MVC</category></item><item><title>Understanding LINQ to SQL (10) Implementing LINQ to SQL Provider</title><link>http://weblogs.asp.net/dixin/archive/2010/05/12/understanding-linq-to-sql-10-implementing-linq-to-sql-provider.aspx</link><pubDate>Tue, 11 May 2010 18:43:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:7479613</guid><dc:creator>Dixin</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/dixin/rsscomments.aspx?PostID=7479613</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/dixin/commentapi.aspx?PostID=7479613</wfw:comment><comments>http://weblogs.asp.net/dixin/archive/2010/05/12/understanding-linq-to-sql-10-implementing-linq-to-sql-provider.aspx#comments</comments><description>&lt;p&gt;[&lt;a href="http://weblogs.asp.net/dixin/archive/2009/09/07/linq-via-csharp.aspx" target="_blank" mce_href="http://weblogs.asp.net/dixin/archive/2009/09/07/linq-via-csharp.aspx"&gt;LINQ via C# series&lt;/a&gt;]&lt;/p&gt;  &lt;p&gt;So far LINQ to SQL data CRUD (Creating / Retrieving / Updating / Deleting) has been explained. This post takes a deeper look at the internal implementation of LINQ to SQL query.&lt;/p&gt;  &lt;h1&gt;The provider model&lt;/h1&gt;  &lt;p&gt;Unlike IEnumerable / IEnumerable&amp;lt;T&amp;gt;,&amp;#160; the IQueryable / IQueryable&amp;lt;T&amp;gt; need a query provider:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;namespace &lt;/span&gt;System.Linq
{
    &lt;span style="color: blue"&gt;public interface &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IQueryable &lt;/span&gt;: &lt;span style="color: #2b91af"&gt;IEnumerable
    &lt;/span&gt;{
        &lt;span style="color: #2b91af"&gt;Type &lt;/span&gt;ElementType { &lt;span style="color: blue"&gt;get&lt;/span&gt;; }

        &lt;span style="color: #2b91af"&gt;Expression &lt;/span&gt;Expression { &lt;span style="color: blue"&gt;get&lt;/span&gt;; }

        &lt;span style="color: #2b91af"&gt;IQueryProvider &lt;/span&gt;&lt;u&gt;Provider&lt;/u&gt; { &lt;span style="color: blue"&gt;get&lt;/span&gt;; }
    }

    &lt;span style="color: blue"&gt;public interface &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IQueryable&lt;/span&gt;&amp;lt;&lt;span style="color: blue"&gt;out &lt;/span&gt;T&amp;gt; : &lt;span style="color: #2b91af"&gt;IEnumerable&lt;/span&gt;&amp;lt;T&amp;gt;, &lt;span style="color: #2b91af"&gt;IQueryable&lt;/span&gt;, &lt;span style="color: #2b91af"&gt;IEnumerable
    &lt;/span&gt;{
    }
}&lt;/pre&gt;

&lt;p&gt;And this is the definition of IQueryProvider:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;namespace &lt;/span&gt;System.Linq
{
    &lt;span style="color: blue"&gt;public interface &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IQueryProvider
    &lt;/span&gt;{
        &lt;span style="color: #2b91af"&gt;IQueryable &lt;/span&gt;CreateQuery(&lt;span style="color: #2b91af"&gt;Expression &lt;/span&gt;expression);

        &lt;span style="color: #2b91af"&gt;IQueryable&lt;/span&gt;&amp;lt;TElement&amp;gt; CreateQuery&amp;lt;TElement&amp;gt;(&lt;span style="color: #2b91af"&gt;Expression &lt;/span&gt;expression);

        &lt;span style="color: blue"&gt;object &lt;/span&gt;Execute(&lt;span style="color: #2b91af"&gt;Expression &lt;/span&gt;expression);

        TResult Execute&amp;lt;TResult&amp;gt;(&lt;span style="color: #2b91af"&gt;Expression &lt;/span&gt;expression);
    }
}&lt;/pre&gt;

&lt;p&gt;Yes, IQueryable / IQueryable&amp;lt;T&amp;gt; are much more complex than IEnumerable / IEnumerable&amp;lt;T&amp;gt;, because they are supposed to work against non-.NET data source, like SQL Server database, etc.&lt;/p&gt;

&lt;p&gt;Please also notice IOrderedQueryable and IOrderedQueryable&amp;lt;T&amp;gt;:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;namespace &lt;/span&gt;System.Linq
{
    &lt;span style="color: green"&gt;// The same as IQueryable.
    &lt;/span&gt;&lt;span style="color: blue"&gt;public interface &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IOrderedQueryable &lt;/span&gt;: &lt;span style="color: #2b91af"&gt;IQueryable&lt;/span&gt;, &lt;span style="color: #2b91af"&gt;IEnumerable
    &lt;/span&gt;{
    }
    
    &lt;span style="color: green"&gt;// The same as IQueryable&amp;lt;T&amp;gt;.
    &lt;/span&gt;&lt;span style="color: blue"&gt;public interface &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IOrderedQueryable&lt;/span&gt;&amp;lt;&lt;span style="color: blue"&gt;out &lt;/span&gt;T&amp;gt; : &lt;span style="color: #2b91af"&gt;IOrderedQueryable&lt;/span&gt;,
                                                &lt;span style="color: #2b91af"&gt;IQueryable&lt;/span&gt;&amp;lt;T&amp;gt;, &lt;span style="color: #2b91af"&gt;IQueryable&lt;/span&gt;,
                                                &lt;span style="color: #2b91af"&gt;IEnumerable&lt;/span&gt;&amp;lt;T&amp;gt;, &lt;span style="color: #2b91af"&gt;IEnumerable
    &lt;/span&gt;{
    }
}&lt;/pre&gt;

&lt;p&gt;They are the same as IQueryable and IQueryable&amp;lt;T&amp;gt;, and just used to represent an ordering query, like OrderBy(), etc.&lt;/p&gt;

&lt;h2&gt;Implement IQueryable&amp;lt;T&amp;gt; and IOrderedQueryable&amp;lt;T&amp;gt;&lt;/h2&gt;

&lt;p&gt;The best way to understand these interfaces is just creating IQueryable / IQueryable&amp;lt;T&amp;gt; objects, and examining how they work and query data from SQL Server.&lt;/p&gt;

&lt;p&gt;This is one simple implementation:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Queryable&lt;/span&gt;&amp;lt;TSource&amp;gt; : &lt;u&gt;&lt;span style="color: #2b91af"&gt;IOrderedQueryable&lt;/span&gt;&amp;lt;TSource&amp;gt;&lt;/u&gt;
{
    &lt;span style="color: blue"&gt;public &lt;/span&gt;Queryable(&lt;span style="color: #2b91af"&gt;IQueryProvider &lt;/span&gt;provider, &lt;span style="color: #2b91af"&gt;IQueryable&lt;/span&gt;&amp;lt;TSource&amp;gt; innerSource)
    {
        &lt;span style="color: blue"&gt;this&lt;/span&gt;.Provider = provider;
        &lt;span style="color: blue"&gt;this&lt;/span&gt;.Expression = &lt;span style="color: #2b91af"&gt;Expression&lt;/span&gt;.Constant(innerSource);
    }

    &lt;span style="color: blue"&gt;public &lt;/span&gt;Queryable(&lt;span style="color: #2b91af"&gt;IQueryProvider &lt;/span&gt;provider, &lt;span style="color: #2b91af"&gt;Expression &lt;/span&gt;expression)
    {
        &lt;span style="color: blue"&gt;this&lt;/span&gt;.Provider = provider;
        &lt;span style="color: blue"&gt;this&lt;/span&gt;.Expression = expression;
    }

    &lt;span style="color: blue"&gt;#region &lt;/span&gt;IEnumerable&amp;lt;TSource&amp;gt; Members

    &lt;span style="color: blue"&gt;public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IEnumerator&lt;/span&gt;&amp;lt;TSource&amp;gt; GetEnumerator()
    {
        &lt;span style="color: blue"&gt;return this&lt;/span&gt;.Provider.Execute&amp;lt;&lt;span style="color: #2b91af"&gt;IEnumerable&lt;/span&gt;&amp;lt;TSource&amp;gt;&amp;gt;(&lt;span style="color: blue"&gt;this&lt;/span&gt;.Expression).GetEnumerator();
    }

    &lt;span style="color: blue"&gt;#endregion

    #region &lt;/span&gt;IEnumerable Members

    &lt;span style="color: #2b91af"&gt;IEnumerator IEnumerable&lt;/span&gt;.GetEnumerator()
    {
        &lt;span style="color: blue"&gt;return this&lt;/span&gt;.GetEnumerator();
    }

    &lt;span style="color: blue"&gt;#endregion

    #region &lt;/span&gt;IQueryable Members

    &lt;span style="color: blue"&gt;public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Type &lt;/span&gt;ElementType
    {
        &lt;span style="color: blue"&gt;get
        &lt;/span&gt;{
            &lt;span style="color: blue"&gt;return typeof&lt;/span&gt;(TSource);
        }
    }

    &lt;span style="color: blue"&gt;public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Expression &lt;/span&gt;Expression
    {
        &lt;span style="color: blue"&gt;get&lt;/span&gt;;
        &lt;span style="color: blue"&gt;private set&lt;/span&gt;;
    }

    &lt;span style="color: blue"&gt;public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IQueryProvider &lt;/span&gt;Provider
    {
        &lt;span style="color: blue"&gt;get&lt;/span&gt;;
        &lt;span style="color: blue"&gt;private set&lt;/span&gt;;
    }

    &lt;span style="color: blue"&gt;#endregion
&lt;/span&gt;}&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Since Queryable&amp;lt;TSource&amp;gt; implements IOrderedQueryable&amp;lt;T&amp;gt;, it also implements IQeryable&amp;lt;TSource&amp;gt;, IQeryable and IOrderedQueryable.&lt;/p&gt;

&lt;p&gt;There is not too much things. The most important method is GetEnumerator(). When a Queryable&amp;lt;TSource&amp;gt; object is iterated to traverse the data items, it simply asks its query provider to execute its expression to retrieve an IEnumerable&amp;lt;TSource&amp;gt; object, and return that object’s iterator.&lt;/p&gt;

&lt;h2&gt;Implement IQueryProvider&lt;/h2&gt;

&lt;p&gt;So the actual SQL query implantation is in the query provider:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;QueryProvider &lt;/span&gt;: &lt;span style="color: #2b91af"&gt;IQueryProvider
&lt;/span&gt;{
    &lt;span style="color: green"&gt;// Translates LINQ query to SQL.
    &lt;/span&gt;&lt;span style="color: blue"&gt;private readonly &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Func&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;IQueryable&lt;/span&gt;, &lt;span style="color: #2b91af"&gt;DbCommand&lt;/span&gt;&amp;gt; _translator;

    &lt;span style="color: green"&gt;// Executes the translated SQL and retrieves results.
    &lt;/span&gt;&lt;span style="color: blue"&gt;private readonly &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Func&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Type&lt;/span&gt;, &lt;span style="color: blue"&gt;string&lt;/span&gt;, &lt;span style="color: blue"&gt;object&lt;/span&gt;[], &lt;span style="color: #2b91af"&gt;IEnumerable&lt;/span&gt;&amp;gt; _executor;

    &lt;span style="color: blue"&gt;public &lt;/span&gt;QueryProvider(
        &lt;span style="color: #2b91af"&gt;Func&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;IQueryable&lt;/span&gt;, &lt;span style="color: #2b91af"&gt;DbCommand&lt;/span&gt;&amp;gt; translator,
        &lt;span style="color: #2b91af"&gt;Func&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Type&lt;/span&gt;, &lt;span style="color: blue"&gt;string&lt;/span&gt;, &lt;span style="color: blue"&gt;object&lt;/span&gt;[], &lt;span style="color: #2b91af"&gt;IEnumerable&lt;/span&gt;&amp;gt; executor)
    {
        &lt;span style="color: blue"&gt;this&lt;/span&gt;._translator = translator;
        &lt;span style="color: blue"&gt;this&lt;/span&gt;._executor = executor;
    }

    &lt;span style="color: blue"&gt;#region &lt;/span&gt;IQueryProvider Members

    &lt;span style="color: blue"&gt;public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IQueryable&lt;/span&gt;&amp;lt;TElement&amp;gt; CreateQuery&amp;lt;TElement&amp;gt;(&lt;span style="color: #2b91af"&gt;Expression &lt;/span&gt;expression)
    {
        &lt;span style="color: blue"&gt;return new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Queryable&lt;/span&gt;&amp;lt;TElement&amp;gt;(&lt;span style="color: blue"&gt;this&lt;/span&gt;, expression);
    }

    &lt;span style="color: blue"&gt;public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IQueryable &lt;/span&gt;CreateQuery(&lt;span style="color: #2b91af"&gt;Expression &lt;/span&gt;expression)
    {
        &lt;span style="color: blue"&gt;throw new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;NotImplementedException&lt;/span&gt;();
    }

    &lt;span style="color: blue"&gt;public &lt;/span&gt;TResult Execute&amp;lt;TResult&amp;gt;(&lt;span style="color: #2b91af"&gt;Expression &lt;/span&gt;expression)
    {
        &lt;span style="color: blue"&gt;bool &lt;/span&gt;isCollection = &lt;span style="color: blue"&gt;typeof&lt;/span&gt;(TResult).IsGenericType &amp;amp;&amp;amp;
            &lt;span style="color: blue"&gt;typeof&lt;/span&gt;(TResult).GetGenericTypeDefinition() == &lt;span style="color: blue"&gt;typeof&lt;/span&gt;(&lt;span style="color: #2b91af"&gt;IEnumerable&lt;/span&gt;&amp;lt;&amp;gt;);
        &lt;span style="color: #2b91af"&gt;Type &lt;/span&gt;itemType = isCollection
            &lt;span style="color: green"&gt;// TResult is an IEnumerable`1 collection.
            &lt;/span&gt;? &lt;span style="color: blue"&gt;typeof&lt;/span&gt;(TResult).GetGenericArguments().Single()
            &lt;span style="color: green"&gt;// TResult is not an IEnumerable`1 collection, but a single item.
            &lt;/span&gt;: &lt;span style="color: blue"&gt;typeof&lt;/span&gt;(TResult);
        &lt;span style="color: #2b91af"&gt;IQueryable &lt;/span&gt;queryable = &lt;span style="color: #2b91af"&gt;Activator&lt;/span&gt;.CreateInstance(
            &lt;span style="color: blue"&gt;typeof&lt;/span&gt;(&lt;span style="color: #2b91af"&gt;Queryable&lt;/span&gt;&amp;lt;&amp;gt;).MakeGenericType(itemType), &lt;span style="color: blue"&gt;this&lt;/span&gt;, expression) &lt;span style="color: blue"&gt;as &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IQueryable&lt;/span&gt;;

        &lt;span style="color: #2b91af"&gt;IEnumerable &lt;/span&gt;queryResult;

        &lt;span style="color: green"&gt;// Translates LINQ query to SQL.
        &lt;/span&gt;&lt;span style="color: blue"&gt;using &lt;/span&gt;(&lt;span style="color: #2b91af"&gt;DbCommand &lt;/span&gt;command = &lt;span style="color: blue"&gt;this&lt;/span&gt;._translator(queryable))
        {
            &lt;span style="color: green"&gt;// Executes the transalted SQL.
            &lt;/span&gt;queryResult = &lt;span style="color: blue"&gt;this&lt;/span&gt;._executor(
                itemType,
                command.CommandText,
                command.Parameters.OfType&amp;lt;&lt;span style="color: #2b91af"&gt;DbParameter&lt;/span&gt;&amp;gt;()
                                  .Select(parameter =&amp;gt; parameter.Value)
                                  .ToArray());
        }

        &lt;span style="color: blue"&gt;return &lt;/span&gt;isCollection
            ? (TResult)queryResult &lt;span style="color: green"&gt;// Returns an IEnumerable`1 collection.
            &lt;/span&gt;: queryResult.OfType&amp;lt;TResult&amp;gt;()
                         .SingleOrDefault(); &lt;span style="color: green"&gt;// Returns a single item.
    &lt;/span&gt;}

    &lt;span style="color: blue"&gt;public object &lt;/span&gt;Execute(&lt;span style="color: #2b91af"&gt;Expression &lt;/span&gt;expression)
    {
        &lt;span style="color: blue"&gt;throw new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;NotImplementedException&lt;/span&gt;();
    }

    &lt;span style="color: blue"&gt;#endregion
&lt;/span&gt;}&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;QueryProvider must be initialized with a translator and executor, so that it is able to translate LINQ query to SQL, and execute the translated SQL.&lt;/p&gt;

&lt;p&gt;And here the most important is the generic Execute() method, which is called by the above Queryable&amp;lt;TSource&amp;gt;.GetEnumerator(). It does the following work:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Checks whether it should return a collection of items (for the Where() scenarios, etc.), or should return a sinlge item (for the Single() query scenarios, etc.) &lt;/li&gt;

  &lt;li&gt;Invokes the translator to translate LINQ query to SQL. &lt;/li&gt;

  &lt;li&gt;Invokes the executor to execute the translated SQL and retrieves the result. &lt;/li&gt;

  &lt;li&gt;Returns result of a proper type (either a collection, or a single item). &lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;Query method internals&lt;/h1&gt;

&lt;p&gt;Before running the query, take a look at the IQueryable&amp;lt;T&amp;gt; query methods. &lt;/p&gt;

&lt;h2&gt;Deferred execution methods&lt;/h2&gt;

&lt;p&gt;Take Where() as an example:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public static class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Queryable
&lt;/span&gt;{
    &lt;span style="color: blue"&gt;public static &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IQueryable&lt;/span&gt;&amp;lt;TSource&amp;gt; Where&amp;lt;TSource&amp;gt;(
        &lt;span style="color: blue"&gt;this &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IQueryable&lt;/span&gt;&amp;lt;TSource&amp;gt; source, &lt;span style="color: #2b91af"&gt;Expression&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Func&lt;/span&gt;&amp;lt;TSource, &lt;span style="color: blue"&gt;bool&lt;/span&gt;&amp;gt;&amp;gt; predicate)
    {
        &lt;span style="color: green"&gt;// Checks arguments.
        &lt;/span&gt;&lt;span style="color: blue"&gt;return &lt;/span&gt;source.Provider.&lt;u&gt;CreateQuery&lt;/u&gt;&amp;lt;TSource&amp;gt;(
            &lt;span style="color: #2b91af"&gt;Expression&lt;/span&gt;.Call(
                &lt;span style="color: blue"&gt;null&lt;/span&gt;,
                ((&lt;span style="color: #2b91af"&gt;MethodInfo&lt;/span&gt;)&lt;span style="color: #2b91af"&gt;MethodBase&lt;/span&gt;.GetCurrentMethod()).MakeGenericMethod(&lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Type&lt;/span&gt;[]
                    { 
                        &lt;span style="color: blue"&gt;typeof&lt;/span&gt;(TSource) 
                    }),
                &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Expression&lt;/span&gt;[] 
                    { 
                        source.Expression, 
                        &lt;span style="color: #2b91af"&gt;Expression&lt;/span&gt;.Quote(predicate) 
                    }));
    }
}&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;It is very very different from &lt;a href="http://weblogs.asp.net/dixin/archive/2010/03/16/understanding-linq-to-objects-7-query-methods-internals.aspx" target="_blank" mce_href="http://weblogs.asp.net/dixin/archive/2010/03/16/understanding-linq-to-objects-7-query-methods-internals.aspx"&gt;IEnumerable&amp;lt;T&amp;gt;’s Where() query method&lt;/a&gt;. It is not executing any thing, it just:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Constructs a new expression tree, which contains the following information: 
    &lt;ul&gt;
      &lt;li&gt;The original expression tree from the source IQueryable&amp;lt;T&amp;gt; object &lt;/li&gt;

      &lt;li&gt;The predicate expression tree &lt;/li&gt;

      &lt;li&gt;This Where() query method is invoked &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;

  &lt;li&gt;Then invokes the query provider’s generic CreateQuery() method to construct a new IQueryable&amp;lt;TSource&amp;gt; object. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Obviously, the above constructed expression tree is used to contain the information which is prepared to be translated.&lt;/p&gt;

&lt;p&gt;The ordering query method, like OrderBy(), is a little different, which converts the constructed IQueryable&amp;lt;TSource&amp;gt; object to an IOrderedQueryable&amp;lt;TSource&amp;gt; object:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public static &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IOrderedQueryable&lt;/span&gt;&amp;lt;TSource&amp;gt; OrderBy&amp;lt;TSource, TKey&amp;gt;(
    &lt;span style="color: blue"&gt;this &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IQueryable&lt;/span&gt;&amp;lt;TSource&amp;gt; source, &lt;span style="color: #2b91af"&gt;Expression&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Func&lt;/span&gt;&amp;lt;TSource, TKey&amp;gt;&amp;gt; keySelector)
{
    &lt;span style="color: green"&gt;// Checks arguments.
    &lt;/span&gt;&lt;span style="color: blue"&gt;return &lt;/span&gt;&lt;u&gt;(&lt;span style="color: #2b91af"&gt;IOrderedQueryable&lt;/span&gt;&amp;lt;TSource&amp;gt;)&lt;/u&gt;source.Provider.CreateQuery&amp;lt;TSource&amp;gt;(
        &lt;span style="color: #2b91af"&gt;Expression&lt;/span&gt;.Call(
            &lt;span style="color: blue"&gt;null&lt;/span&gt;, 
            ((&lt;span style="color: #2b91af"&gt;MethodInfo&lt;/span&gt;)&lt;span style="color: #2b91af"&gt;MethodBase&lt;/span&gt;.GetCurrentMethod()).MakeGenericMethod(&lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Type&lt;/span&gt;[] 
                { 
                    &lt;span style="color: blue"&gt;typeof&lt;/span&gt;(TSource), 
                    &lt;span style="color: blue"&gt;typeof&lt;/span&gt;(TKey) 
                }), 
            &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Expression&lt;/span&gt;[] 
                { 
                    source.Expression, 
                    &lt;span style="color: #2b91af"&gt;Expression&lt;/span&gt;.Quote(keySelector) 
                }));
}&lt;/pre&gt;

&lt;p&gt;And so is ThenBy():&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public static &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IOrderedQueryable&lt;/span&gt;&amp;lt;TSource&amp;gt; ThenBy&amp;lt;TSource, TKey&amp;gt;(
    &lt;span style="color: blue"&gt;this &lt;/span&gt;&lt;u&gt;&lt;span style="color: #2b91af"&gt;IOrderedQueryable&lt;/span&gt;&amp;lt;TSource&amp;gt;&lt;/u&gt; source, &lt;span style="color: #2b91af"&gt;Expression&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Func&lt;/span&gt;&amp;lt;TSource, TKey&amp;gt;&amp;gt; keySelector)
{
    &lt;span style="color: green"&gt;// Checks arguments.
    &lt;/span&gt;&lt;span style="color: blue"&gt;return &lt;/span&gt;(&lt;span style="color: #2b91af"&gt;IOrderedQueryable&lt;/span&gt;&amp;lt;TSource&amp;gt;)source.Provider.CreateQuery&amp;lt;TSource&amp;gt;(
        &lt;span style="color: #2b91af"&gt;Expression&lt;/span&gt;.Call(
            &lt;span style="color: blue"&gt;null&lt;/span&gt;, 
            ((&lt;span style="color: #2b91af"&gt;MethodInfo&lt;/span&gt;)&lt;span style="color: #2b91af"&gt;MethodBase&lt;/span&gt;.GetCurrentMethod()).MakeGenericMethod(&lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Type&lt;/span&gt;[] 
                { 
                    &lt;span style="color: blue"&gt;typeof&lt;/span&gt;(TSource), 
                    &lt;span style="color: blue"&gt;typeof&lt;/span&gt;(TKey) 
                }), 
            &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Expression&lt;/span&gt;[] { 
                    source.Expression, 
                    &lt;span style="color: #2b91af"&gt;Expression&lt;/span&gt;.Quote(keySelector) 
            }));
}&lt;/pre&gt;

&lt;p&gt;ThenBy() / ThenByDescending() are extension methods of IOrderedQueryable&amp;lt;TSource&amp;gt; instead of IQueryable&amp;lt;TSource&amp;gt;, which means, It must be invoked after invoking OrderBy() / OrderByDescending().&lt;/p&gt;

&lt;h2&gt;Eager execution methods&lt;/h2&gt;

&lt;p&gt;Single() is different:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public static &lt;/span&gt;TSource Single&amp;lt;TSource&amp;gt;(&lt;span style="color: blue"&gt;this &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IQueryable&lt;/span&gt;&amp;lt;TSource&amp;gt; source)
{
    &lt;span style="color: green"&gt;// Checks arguments.
    &lt;/span&gt;&lt;span style="color: blue"&gt;return &lt;/span&gt;source.Provider.&lt;u&gt;Execute&lt;/u&gt;&amp;lt;TSource&amp;gt;(
        &lt;span style="color: #2b91af"&gt;Expression&lt;/span&gt;.Call(
            &lt;span style="color: blue"&gt;null&lt;/span&gt;, 
            ((&lt;span style="color: #2b91af"&gt;MethodInfo&lt;/span&gt;)&lt;span style="color: #2b91af"&gt;MethodBase&lt;/span&gt;.GetCurrentMethod()).MakeGenericMethod(&lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Type&lt;/span&gt;[] 
                { 
                    &lt;span style="color: blue"&gt;typeof&lt;/span&gt;(TSource) 
                }), 
            &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Expression&lt;/span&gt;[] 
                { 
                    source.Expression 
                }));
}&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Logically, Single() cannot be deferred. So after construction the expression tree, it invokes query provider’s generic Execute() method, and returns a TSource object instead of a IQueryable&amp;lt;TSource&amp;gt;.&lt;/p&gt;

&lt;p&gt;Of course, the aggregate methods looks similar, invoking Execute() instead of CreateQuery():&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public static decimal &lt;/span&gt;Average&amp;lt;TSource&amp;gt;(
    &lt;span style="color: blue"&gt;this &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IQueryable&lt;/span&gt;&amp;lt;TSource&amp;gt; source, &lt;span style="color: #2b91af"&gt;Expression&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Func&lt;/span&gt;&amp;lt;TSource, &lt;span style="color: blue"&gt;decimal&lt;/span&gt;&amp;gt;&amp;gt; selector)
{
    &lt;span style="color: green"&gt;// Checks arguments.
    &lt;/span&gt;&lt;span style="color: blue"&gt;return &lt;/span&gt;source.Provider.&lt;u&gt;Execute&lt;/u&gt;&amp;lt;&lt;span style="color: blue"&gt;decimal&lt;/span&gt;&amp;gt;(
        &lt;span style="color: #2b91af"&gt;Expression&lt;/span&gt;.Call(
            &lt;span style="color: blue"&gt;null&lt;/span&gt;, 
            ((&lt;span style="color: #2b91af"&gt;MethodInfo&lt;/span&gt;)&lt;span style="color: #2b91af"&gt;MethodBase&lt;/span&gt;.GetCurrentMethod()).MakeGenericMethod(&lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Type&lt;/span&gt;[] 
                { 
                    &lt;span style="color: blue"&gt;typeof&lt;/span&gt;(TSource) 
                }), 
            &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Expression&lt;/span&gt;[] 
                { 
                    source.Expression, 
                    &lt;span style="color: #2b91af"&gt;Expression&lt;/span&gt;.Quote(selector) 
                }));
}&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;It cannot be deferred either.&lt;/p&gt;

&lt;h1&gt;Work together&lt;/h1&gt;

&lt;p&gt;Now it is ready to run all the stuff above.&lt;/p&gt;

&lt;h2&gt;Query a collection of items (deferred execution)&lt;/h2&gt;

&lt;p&gt;The following query expects a collection of Product objects:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;using &lt;/span&gt;(&lt;span style="color: #2b91af"&gt;NorthwindDataContext &lt;/span&gt;database = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;NorthwindDataContext&lt;/span&gt;())
{
    &lt;span style="color: #2b91af"&gt;IQueryProvider &lt;/span&gt;provider = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;QueryProvider&lt;/span&gt;(database.GetCommand, database.ExecuteQuery);
    &lt;span style="color: #2b91af"&gt;IQueryable&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Product&lt;/span&gt;&amp;gt; source = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Queryable&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Product&lt;/span&gt;&amp;gt;(provider, database.GetTable&amp;lt;&lt;span style="color: #2b91af"&gt;Product&lt;/span&gt;&amp;gt;());
    &lt;span style="color: #2b91af"&gt;IQueryable&lt;/span&gt;&amp;lt;&lt;span style="color: blue"&gt;string&lt;/span&gt;&amp;gt; results = source.Where(product =&amp;gt; product.CategoryID == 2)
                                       .OrderBy(product =&amp;gt; product.ProductName)
                                       .Select(product =&amp;gt; product.ProductName)
                                       .Skip(5)
                                       .Take(10);

    &lt;span style="color: blue"&gt;using &lt;/span&gt;(&lt;span style="color: #2b91af"&gt;IEnumerator&lt;/span&gt;&amp;lt;&lt;span style="color: blue"&gt;string&lt;/span&gt;&amp;gt; iterator = results.GetEnumerator())
    {
        &lt;span style="color: blue"&gt;while &lt;/span&gt;(iterator.MoveNext())
        {
            &lt;span style="color: blue"&gt;string &lt;/span&gt;item = iterator.Current;
            &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.WriteLine(item);
        }
    }
}&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;To initialize the provider, DataContext.GetCommand() and DataContext.ExecuteQuery() are passed as translator and executor.&lt;/p&gt;

&lt;p&gt;When results.GetEnumerator() is invoked, provider.Execute() is invoked. The query is translated to:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;exec &lt;/span&gt;&lt;span style="color: maroon"&gt;sp_executesql &lt;/span&gt;&lt;span style="color: red"&gt;N'SELECT [t1].[ProductName]
FROM (
    SELECT ROW_NUMBER() OVER (ORDER BY [t0].[ProductName]) AS [ROW_NUMBER], [t0].[ProductName]
    FROM [dbo].[Products] AS [t0]
    WHERE [t0].[CategoryID] &amp;gt; @p0
    ) AS [t1]
WHERE [t1].[ROW_NUMBER] BETWEEN @p1 + 1 AND @p1 + @p2
ORDER BY [t1].[ROW_NUMBER]'&lt;/span&gt;&lt;span style="color: gray"&gt;,&lt;/span&gt;&lt;span style="color: red"&gt;N'@p0 int,@p1 int,@p2 int'&lt;/span&gt;&lt;span style="color: gray"&gt;,&lt;/span&gt;&lt;span style="color: teal"&gt;@p0&lt;/span&gt;&lt;span style="color: gray"&gt;=&lt;/span&gt;2&lt;span style="color: gray"&gt;,&lt;/span&gt;&lt;span style="color: teal"&gt;@p1&lt;/span&gt;&lt;span style="color: gray"&gt;=&lt;/span&gt;5&lt;span style="color: gray"&gt;,&lt;/span&gt;&lt;span style="color: teal"&gt;@p2&lt;/span&gt;&lt;span style="color: gray"&gt;=&lt;/span&gt;10&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;by the provider’s translator, then provider’s executor executes the above SQL in SQL Server, and return a collection of items.&lt;/p&gt;

&lt;p&gt;This is the printed output:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Escargots de Bourgogne 
    &lt;br /&gt;Filo Mix 

    &lt;br /&gt;Flotemysost 

    &lt;br /&gt;Geitost 

    &lt;br /&gt;Gnocchi di nonna Alice 

    &lt;br /&gt;Gorgonzola Telino 

    &lt;br /&gt;Gravad lax 

    &lt;br /&gt;Gudbrandsdalsost 

    &lt;br /&gt;Gumbär Gummibärchen 

    &lt;br /&gt;Gustaf's Knäckebröd&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;Query a single item (eager execution)&lt;/h2&gt;

&lt;p&gt;The following sample is different:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: #2b91af"&gt;IQueryProvider &lt;/span&gt;provider = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;QueryProvider&lt;/span&gt;(database.GetCommand, database.ExecuteQuery);
&lt;span style="color: #2b91af"&gt;IQueryable&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Product&lt;/span&gt;&amp;gt; source = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Queryable&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Product&lt;/span&gt;&amp;gt;(provider, database.GetTable&amp;lt;&lt;span style="color: #2b91af"&gt;Product&lt;/span&gt;&amp;gt;());
&lt;span style="color: blue"&gt;string &lt;/span&gt;productName = source.Where(product =&amp;gt; product.CategoryID &amp;gt; 2)
                           .Select(product =&amp;gt; product.ProductName)
                           .First();&lt;/pre&gt;

&lt;p&gt;Without deferred execution and iterating, the First() invokes provider.Execute() directly.&lt;/p&gt;

&lt;p&gt;This is the translated SQL:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;exec &lt;/span&gt;&lt;span style="color: maroon"&gt;sp_executesql &lt;/span&gt;&lt;span style="color: red"&gt;N'SELECT TOP (1) [t0].[ProductName]
FROM [dbo].[Products] AS [t0]
WHERE [t0].[CategoryID] &amp;gt; @p0'&lt;/span&gt;&lt;span style="color: gray"&gt;,&lt;/span&gt;&lt;span style="color: red"&gt;N'@p0 int'&lt;/span&gt;&lt;span style="color: gray"&gt;,&lt;/span&gt;&lt;span style="color: teal"&gt;@p0&lt;/span&gt;&lt;span style="color: gray"&gt;=&lt;/span&gt;2&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;h2&gt;Aggregate (eager execution)&lt;/h2&gt;

&lt;p&gt;Aggregate query is also eager:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: #2b91af"&gt;IQueryProvider &lt;/span&gt;provider = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;QueryProvider&lt;/span&gt;(database.GetCommand, database.ExecuteQuery);
&lt;span style="color: #2b91af"&gt;IQueryable&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Product&lt;/span&gt;&amp;gt; source = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Queryable&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Product&lt;/span&gt;&amp;gt;(provider, database.GetTable&amp;lt;&lt;span style="color: #2b91af"&gt;Product&lt;/span&gt;&amp;gt;());
&lt;span style="color: blue"&gt;decimal &lt;/span&gt;averagePrice = source.Where(product =&amp;gt; product.CategoryID == 2)
                             .Average(product =&amp;gt; product.UnitPrice.GetValueOrDefault());&lt;/pre&gt;

&lt;p&gt;This is the translated SQL:&lt;a href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;exec &lt;/span&gt;&lt;span style="color: maroon"&gt;sp_executesql &lt;/span&gt;&lt;span style="color: red"&gt;N'SELECT AVG([t1].[value]) AS [value]
FROM (
    SELECT COALESCE([t0].[UnitPrice],0) AS [value], [t0].[CategoryID]
    FROM [dbo].[Products] AS [t0]
    ) AS [t1]
WHERE [t1].[CategoryID] = @p0'&lt;/span&gt;&lt;span style="color: gray"&gt;,&lt;/span&gt;&lt;span style="color: red"&gt;N'@p0 int'&lt;/span&gt;&lt;span style="color: gray"&gt;,&lt;/span&gt;&lt;span style="color: teal"&gt;@p0&lt;/span&gt;&lt;span style="color: gray"&gt;=&lt;/span&gt;2&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;h2&gt;SQL translating and executing&lt;/h2&gt;

&lt;p mce_keep="true"&gt;The above samples explained the implementation of LINQ to SQL query and query provider. Inside the QueryProvider class, it does not provide the detailed implementation of SQL translating and executing, but pass the work to DataContext.GetCommand() and DataContext.ExecuteQuery().&lt;/p&gt;

&lt;p&gt;&lt;a href="http://weblogs.asp.net/dixin/archive/2010/04/06/understanding-linq-to-sql-3-expression-tree.aspx" target="_blank" mce_href="http://weblogs.asp.net/dixin/archive/2010/04/06/understanding-linq-to-sql-3-expression-tree.aspx"&gt;This post&lt;/a&gt; has demonstrated the simplest SQL translating and executing. But the realistic work is very very complex. Since this is not a SQL series but a LINQ / functional programming series, to develop a full featured SQL “compiler” is far beyond this series’ scope. For SQL executing, it is also complex to convert the retrieved data back to strong-typed objects in LINQ to SQL. To understand the entire translating and executing process, please follow the source code of Table&amp;lt;T&amp;gt;, which implements IQueryProvider.&lt;/p&gt;

&lt;p&gt;Internally, Table&amp;lt;T&amp;gt; uses several internal classes, like SqlProvider, QueryConverter, etc., to accomplish the translating. For example, one of the core APIs is the QueryConverter.VisitSequenceOperatorCall():&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;internal class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;QueryConverter
&lt;/span&gt;{
    &lt;span style="color: blue"&gt;private &lt;/span&gt;&lt;span style="color: #2b91af"&gt;SqlNode &lt;/span&gt;VisitSequenceOperatorCall(&lt;span style="color: #2b91af"&gt;MethodCallExpression &lt;/span&gt;mc)
    {
        &lt;span style="color: #2b91af"&gt;Type &lt;/span&gt;declaringType = mc.Method.DeclaringType;
        &lt;span style="color: blue"&gt;if &lt;/span&gt;(!(declaringType == &lt;span style="color: blue"&gt;typeof&lt;/span&gt;(&lt;span style="color: #2b91af"&gt;Enumerable&lt;/span&gt;)) &amp;amp;&amp;amp; !(declaringType == &lt;span style="color: blue"&gt;typeof&lt;/span&gt;(&lt;span style="color: #2b91af"&gt;Queryable&lt;/span&gt;)))
        {
            &lt;span style="color: blue"&gt;throw new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;InvalidOperationException&lt;/span&gt;(&lt;span style="color: blue"&gt;string&lt;/span&gt;.Format(
                &lt;span style="color: #2b91af"&gt;CultureInfo&lt;/span&gt;.InvariantCulture,
                &lt;span style="color: #a31515"&gt;&amp;quot;Sequence operator call is only valid for Sequence, Queryable, or DataQueryExtensions not for '{0}'&amp;quot;&lt;/span&gt;,
                declaringType));
        }

        &lt;span style="color: blue"&gt;bool &lt;/span&gt;isNotSupported = &lt;span style="color: blue"&gt;false&lt;/span&gt;;
        &lt;span style="color: blue"&gt;switch &lt;/span&gt;(mc.Method.Name)
        {
            &lt;span style="color: blue"&gt;case &lt;/span&gt;&lt;span style="color: #a31515"&gt;&amp;quot;Where&amp;quot;&lt;/span&gt;:
                isNotSupported = &lt;span style="color: blue"&gt;true&lt;/span&gt;;

                &lt;span style="color: green"&gt;// The overload:
                // IQueryable&amp;lt;TSource&amp;gt; Where&amp;lt;TSource&amp;gt;(
                // this IQueryable&amp;lt;TSource&amp;gt; source, Expression&amp;lt;Func&amp;lt;TSource, int, bool&amp;gt;&amp;gt; predicate)
                // is not supported.

                // The MethodCallExpression object mc should have 2 arguments.
                // The first argument should be null.
                // The second argument should be Expression.Quote(predicate).
                &lt;/span&gt;&lt;span style="color: blue"&gt;if &lt;/span&gt;(mc.Arguments.Count != 2 ||
                    &lt;span style="color: green"&gt;// IsLambda() removes the quote to get the predicate object,
                    // and checks predicate.NodeType ==  ExpressionType.Lambda.
                    &lt;/span&gt;!&lt;span style="color: blue"&gt;this&lt;/span&gt;.IsLambda(mc.Arguments[1]) ||
                    &lt;span style="color: green"&gt;// precicate should have 1 TSource argument.
                    &lt;/span&gt;&lt;span style="color: blue"&gt;this&lt;/span&gt;.GetLambda(mc.Arguments[1]).Parameters.Count != 1)
                {
                    &lt;span style="color: blue"&gt;break&lt;/span&gt;; &lt;span style="color: green"&gt;// The overload is not supported.
                &lt;/span&gt;}

                &lt;span style="color: green"&gt;// The overload:
                // IQueryable&amp;lt;TSource&amp;gt; Where&amp;lt;TSource&amp;gt;(
                // this IQueryable&amp;lt;TSource&amp;gt; source, Expression&amp;lt;Func&amp;lt;TSource, bool&amp;gt;&amp;gt; predicate)
                // is supported.
                &lt;/span&gt;&lt;span style="color: blue"&gt;return this&lt;/span&gt;.VisitWhere(mc.Arguments[0], &lt;span style="color: blue"&gt;this&lt;/span&gt;.GetLambda(mc.Arguments[1]));

            &lt;span style="color: blue"&gt;case &lt;/span&gt;&lt;span style="color: #a31515"&gt;&amp;quot;OrderBy&amp;quot;&lt;/span&gt;:
                isNotSupported = &lt;span style="color: blue"&gt;true&lt;/span&gt;;

                &lt;span style="color: blue"&gt;if &lt;/span&gt;(mc.Arguments.Count != 2 || !&lt;span style="color: blue"&gt;this&lt;/span&gt;.IsLambda(mc.Arguments[1]) ||
                    &lt;span style="color: blue"&gt;this&lt;/span&gt;.GetLambda(mc.Arguments[1]).Parameters.Count != 1)
                {
                    &lt;span style="color: blue"&gt;break&lt;/span&gt;; &lt;span style="color: green"&gt;// The overload is not supported.
                &lt;/span&gt;}

                &lt;span style="color: blue"&gt;return this&lt;/span&gt;.VisitOrderBy(
                    mc.Arguments[0], &lt;span style="color: blue"&gt;this&lt;/span&gt;.GetLambda(mc.Arguments[1]), SqlOrderType.Ascending);

            &lt;span style="color: blue"&gt;case &lt;/span&gt;&lt;span style="color: #a31515"&gt;&amp;quot;ThenBy&amp;quot;&lt;/span&gt;:
                isNotSupported = &lt;span style="color: blue"&gt;true&lt;/span&gt;;

                &lt;span style="color: blue"&gt;if &lt;/span&gt;(mc.Arguments.Count != 2 || !&lt;span style="color: blue"&gt;this&lt;/span&gt;.IsLambda(mc.Arguments[1]) ||
                    &lt;span style="color: blue"&gt;this&lt;/span&gt;.GetLambda(mc.Arguments[1]).Parameters.Count != 1)
                {
                    &lt;span style="color: blue"&gt;break&lt;/span&gt;; &lt;span style="color: green"&gt;// The overload is not supported.
                &lt;/span&gt;}

                &lt;span style="color: blue"&gt;return this&lt;/span&gt;.VisitThenBy(
                    mc.Arguments[0], &lt;span style="color: blue"&gt;this&lt;/span&gt;.GetLambda(mc.Arguments[1]), SqlOrderType.Ascending);

            &lt;span style="color: blue"&gt;case &lt;/span&gt;&lt;span style="color: #a31515"&gt;&amp;quot;Single&amp;quot;&lt;/span&gt;:
            &lt;span style="color: blue"&gt;case &lt;/span&gt;&lt;span style="color: #a31515"&gt;&amp;quot;SingleOrDefault&amp;quot;&lt;/span&gt;:
                isNotSupported = &lt;span style="color: blue"&gt;true&lt;/span&gt;;

                &lt;span style="color: blue"&gt;if &lt;/span&gt;(mc.Arguments.Count != 1)
                {
                    &lt;span style="color: blue"&gt;if &lt;/span&gt;(mc.Arguments.Count != 2 || !&lt;span style="color: blue"&gt;this&lt;/span&gt;.IsLambda(mc.Arguments[1]) ||
                        &lt;span style="color: blue"&gt;this&lt;/span&gt;.GetLambda(mc.Arguments[1]).Parameters.Count != 1)
                    {
                        &lt;span style="color: blue"&gt;break&lt;/span&gt;; &lt;span style="color: green"&gt;// The overload is not supported.
                    &lt;/span&gt;}

                    &lt;span style="color: blue"&gt;return this&lt;/span&gt;.VisitFirst(
                        mc.Arguments[0], &lt;span style="color: blue"&gt;this&lt;/span&gt;.GetLambda(mc.Arguments[1]), &lt;span style="color: blue"&gt;false&lt;/span&gt;);
                }

                &lt;span style="color: blue"&gt;return this&lt;/span&gt;.VisitFirst(mc.Arguments[0], &lt;span style="color: blue"&gt;null&lt;/span&gt;, &lt;span style="color: blue"&gt;false&lt;/span&gt;);

            &lt;span style="color: blue"&gt;case &lt;/span&gt;&lt;span style="color: #a31515"&gt;&amp;quot;Average&amp;quot;&lt;/span&gt;:
                isNotSupported = &lt;span style="color: blue"&gt;true&lt;/span&gt;;

                &lt;span style="color: blue"&gt;if &lt;/span&gt;(mc.Arguments.Count != 1)
                {
                    &lt;span style="color: blue"&gt;if &lt;/span&gt;(mc.Arguments.Count != 2 || !&lt;span style="color: blue"&gt;this&lt;/span&gt;.IsLambda(mc.Arguments[1]) ||
                        &lt;span style="color: blue"&gt;this&lt;/span&gt;.GetLambda(mc.Arguments[1]).Parameters.Count != 1)
                    {
                        &lt;span style="color: blue"&gt;break&lt;/span&gt;; &lt;span style="color: green"&gt;// The overload is not supported.
                    &lt;/span&gt;}

                    &lt;span style="color: blue"&gt;return this&lt;/span&gt;.VisitAggregate(
                        mc.Arguments[0], &lt;span style="color: blue"&gt;this&lt;/span&gt;.GetLambda(mc.Arguments[1]), &lt;span style="color: #2b91af"&gt;SqlNodeType&lt;/span&gt;.Avg, mc.Type);
                }

                &lt;span style="color: blue"&gt;return this&lt;/span&gt;.VisitAggregate(mc.Arguments[0], &lt;span style="color: blue"&gt;null&lt;/span&gt;, &lt;span style="color: #2b91af"&gt;SqlNodeType&lt;/span&gt;.Avg, mc.Type);

            &lt;span style="color: green"&gt;// Other cases, like &amp;quot;Take&amp;quot;, &amp;quot;Skip&amp;quot;, &amp;quot;Distinct&amp;quot;, etc.                
        &lt;/span&gt;}

        &lt;span style="color: blue"&gt;if &lt;/span&gt;(isNotSupported)
        {
            &lt;span style="color: blue"&gt;throw new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;NotSupportedException&lt;/span&gt;(&lt;span style="color: blue"&gt;string&lt;/span&gt;.Format(
                &lt;span style="color: #2b91af"&gt;CultureInfo&lt;/span&gt;.InvariantCulture,
                &lt;span style="color: #a31515"&gt;&amp;quot;Unsupported overload used for query operator '{0}'.&amp;quot;&lt;/span&gt;,
                mc.Method.Name));
        }

        &lt;span style="color: blue"&gt;throw new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;NotSupportedException&lt;/span&gt;(&lt;span style="color: blue"&gt;string&lt;/span&gt;.Format(
            &lt;span style="color: #2b91af"&gt;CultureInfo&lt;/span&gt;.InvariantCulture,
            &lt;span style="color: #a31515"&gt;&amp;quot;The query operator '{0}' is not supported.&amp;quot;&lt;/span&gt;,
            mc.Method.Name));
    }
}&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Please compare this with the fore mentioned IQueryable&amp;lt;T&amp;gt; query methods, Where(), OrderBy(), Single(), Average(), etc.&lt;/p&gt;

&lt;p&gt;There is also &lt;a href="http://msdn.microsoft.com/en-us/vcsharp/ee672195.aspx" target="_blank" mce_href="http://msdn.microsoft.com/en-us/vcsharp/ee672195.aspx"&gt;an excellent tutorial&lt;/a&gt; from MSDN.&lt;/p&gt;

&lt;h1&gt;LINQ Providers&lt;/h1&gt;

&lt;p&gt;There are several kinds of built-in LINQ in .NET 4.0:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/bb397919.aspx" target="_blank" mce_href="http://msdn.microsoft.com/en-us/library/bb397919.aspx"&gt;LINQ to Objects&lt;/a&gt; 

    &lt;ul&gt;
      &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/dd460688.aspx" target="_blank" mce_href="http://msdn.microsoft.com/en-us/library/dd460688.aspx"&gt;Parallel LINQ to Objects&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/bb387098.aspx" target="_blank" mce_href="http://msdn.microsoft.com/en-us/library/bb387098.aspx"&gt;LINQ to XML&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/bb397942.aspx" target="_blank" mce_href="http://msdn.microsoft.com/en-us/library/bb397942.aspx"&gt;LINQ to ADO.NET&lt;/a&gt; 

    &lt;ul&gt;
      &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/bb386976.aspx" target="_blank" mce_href="http://msdn.microsoft.com/en-us/library/bb386976.aspx"&gt;LINQ to SQL&lt;/a&gt; &lt;/li&gt;

      &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/bb386977.aspx" target="_blank" mce_href="http://msdn.microsoft.com/en-us/library/bb386977.aspx"&gt;LINQ to DataSet&lt;/a&gt; &lt;/li&gt;

      &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/bb386964.aspx" target="_blank" mce_href="http://msdn.microsoft.com/en-us/library/bb386964.aspx"&gt;LINQ to Entities&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/bb399365.aspx" target="_blank" mce_href="http://msdn.microsoft.com/en-us/library/bb399365.aspx"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="built-in-linq" border="0" alt="built-in-linq" src="http://weblogs.asp.net/blogs/dixin/builtinlinq_12A094FC.gif" width="458" height="319" mce_src="http://weblogs.asp.net/blogs/dixin/builtinlinq_12A094FC.gif" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;

&lt;h2&gt;Built-in IQueryable LINQ Providers&lt;/h2&gt;

&lt;p&gt;LINQ to Objects and LINQ to XML are IEnumerable based, and the 3 kinds of LINQ to ADO.NET are IQueryable-based, which have their specific IQueryProvider. &lt;/p&gt;

&lt;p&gt;For example, in LINQ to SQL, the IQueryable, IQueryable&amp;lt;T&amp;gt; and IQueryProvider are implemented by Table&amp;lt;T&amp;gt; class and an internal DataQuery&amp;lt;T&amp;gt; class. DataQuery&amp;lt;T&amp;gt; also implements IOrderedQueryable and IOrderedQueryable&amp;lt;T&amp;gt;. These classes and all the other related classes (like SqlProvider, ) can be considered the &lt;u&gt;provider&lt;/u&gt; of LINQ to SQL. &lt;/p&gt;

&lt;h2&gt;LINQ to Everything&lt;/h2&gt;

&lt;p&gt;To implement any other LINQ query against a specific data source, the specific LINQ provider should be provided. That is, classes which implements the above IQueryable, IQueryable&amp;lt;T&amp;gt;, IQueryProvider, IOrderedQueryable and IOrderedQueryable&amp;lt;T&amp;gt; interfaces. The &lt;a href="http://linqtowikipedia.codeplex.com/" target="_blank" mce_href="http://linqtowikipedia.codeplex.com/"&gt;LINQ to Wikipedia&lt;/a&gt; provider &lt;a href="http://weblogs.asp.net/dixin/archive/2009/11/24/introducing-linq-1-what-is-linq.aspx" target="_blank" mce_href="http://weblogs.asp.net/dixin/archive/2009/11/24/introducing-linq-1-what-is-linq.aspx"&gt;at the beginning of the series&lt;/a&gt; is one example. &lt;a href="http://blogs.msdn.com/charlie/archive/2008/02/28/link-to-everything-a-list-of-linq-providers.aspx" target="_blank" mce_href="http://blogs.msdn.com/charlie/archive/2008/02/28/link-to-everything-a-list-of-linq-providers.aspx"&gt;This post&lt;/a&gt; lists a lot of custom LINQ providers, like:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://www.codeplex.com/xlslinq" target="_blank" mce_href="http://www.codeplex.com/xlslinq"&gt;LINQ to Excel&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://www.codeplex.com/LINQtoSharePoint" target="_blank" mce_href="http://www.codeplex.com/LINQtoSharePoint"&gt;LINQ to Sharepoint&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://bloggingabout.net/blogs/emile/archive/2005/12/12/10514.aspx" target="_blank" mce_href="http://bloggingabout.net/blogs/emile/archive/2005/12/12/10514.aspx"&gt;LINQ to WMI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/bb546158.aspx" target="_blank" mce_href="http://msdn.microsoft.com/en-us/library/bb546158.aspx"&gt;This tutorial&lt;/a&gt; teaches how to create a IQueryable LINQ provider against the &lt;a href="http://go.microsoft.com/fwlink/?LinkId=98557" target="_blank" mce_href="http://go.microsoft.com/fwlink/?LinkId=98557"&gt;TerraServer-USA Web service&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;LINQ to Objects provider&lt;/h2&gt;

&lt;p mce_keep="true"&gt;LINQ to Objects is IEnumerable based, but the interesting thing is, IEnumerble&amp;lt;T&amp;gt; has an AsQueryable() extension method, which turns IEnumerble-based query into IQueryable-based query:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public static class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Queryable
&lt;/span&gt;{
    &lt;span style="color: blue"&gt;public static &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IQueryable&lt;/span&gt;&amp;lt;TElement&amp;gt; AsQueryable&amp;lt;TElement&amp;gt;(
        &lt;span style="color: blue"&gt;this &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IEnumerable&lt;/span&gt;&amp;lt;TElement&amp;gt; source)
    {
        &lt;span style="color: green"&gt;// Checks arguments.
        &lt;/span&gt;&lt;span style="color: blue"&gt;if &lt;/span&gt;(source &lt;span style="color: blue"&gt;is &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IQueryable&lt;/span&gt;&amp;lt;TElement&amp;gt;)
        {
            &lt;span style="color: blue"&gt;return &lt;/span&gt;(&lt;span style="color: #2b91af"&gt;IQueryable&lt;/span&gt;&amp;lt;TElement&amp;gt;)source;
        }

        &lt;span style="color: blue"&gt;return new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;EnumerableQuery&lt;/span&gt;&amp;lt;TElement&amp;gt;(source);
    }
}&lt;/pre&gt;

&lt;p&gt;Here the EnumerableQuery&amp;lt;T&amp;gt; class implements IQueryable&amp;lt;T&amp;gt;, as well as the IQueryProvider:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;namespace &lt;/span&gt;System.Linq
{
    &lt;span style="color: blue"&gt;public abstract class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;EnumerableQuery
    &lt;/span&gt;{
        &lt;span style="color: green"&gt;// ...
    &lt;/span&gt;}

    &lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;EnumerableQuery&lt;/span&gt;&amp;lt;T&amp;gt; : &lt;span style="color: #2b91af"&gt;EnumerableQuery&lt;/span&gt;, &lt;span style="color: #2b91af"&gt;&lt;u&gt;IQueryProvider&lt;/u&gt;&lt;/span&gt;,
                                      &lt;u&gt;&lt;span style="color: #2b91af"&gt;IQueryable&lt;/span&gt;&amp;lt;T&amp;gt;&lt;/u&gt;, &lt;span style="color: #2b91af"&gt;IQueryable&lt;/span&gt;,
                                      &lt;span style="color: #2b91af"&gt;IOrderedQueryable&lt;/span&gt;&amp;lt;T&amp;gt;, &lt;span style="color: #2b91af"&gt;IOrderedQueryable&lt;/span&gt;,
                                      &lt;span style="color: #2b91af"&gt;IEnumerable&lt;/span&gt;&amp;lt;T&amp;gt;, &lt;span style="color: #2b91af"&gt;IEnumerable
    &lt;/span&gt;{
        &lt;span style="color: green"&gt;// ...
    &lt;/span&gt;}
}&lt;/pre&gt;

&lt;p&gt;Internally, EnumerableQuery&amp;lt;T&amp;gt;.Execute() invokes Expression&amp;lt;TDelegate&amp;gt;.Compile() to execute the expression representing the query.&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=7479613" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/dixin/archive/tags/.NET/default.aspx">.NET</category><category domain="http://weblogs.asp.net/dixin/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://weblogs.asp.net/dixin/archive/tags/LINQ/default.aspx">LINQ</category><category domain="http://weblogs.asp.net/dixin/archive/tags/TSQL/default.aspx">TSQL</category><category domain="http://weblogs.asp.net/dixin/archive/tags/LINQ+via+C_2300_+Series/default.aspx">LINQ via C# Series</category><category domain="http://weblogs.asp.net/dixin/archive/tags/LINQ+to+SQL/default.aspx">LINQ to SQL</category></item><item><title>Understanding LINQ to SQL (9) Concurrent Conflict</title><link>http://weblogs.asp.net/dixin/archive/2010/04/26/understanding-linq-to-sql-9-concurrent-conflict.aspx</link><pubDate>Mon, 26 Apr 2010 13:53:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:7460505</guid><dc:creator>Dixin</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/dixin/rsscomments.aspx?PostID=7460505</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/dixin/commentapi.aspx?PostID=7460505</wfw:comment><comments>http://weblogs.asp.net/dixin/archive/2010/04/26/understanding-linq-to-sql-9-concurrent-conflict.aspx#comments</comments><description>&lt;P&gt;[&lt;A href="http://weblogs.asp.net/dixin/archive/2009/09/07/linq-via-csharp.aspx" target=_blank s_oid="http://weblogs.asp.net/dixin/archive/2009/09/07/linq-via-csharp.aspx" s_oidt="0" mce_href="http://weblogs.asp.net/dixin/archive/2009/09/07/linq-via-csharp.aspx"&gt;&lt;FONT color=#0066cc&gt;LINQ via C# series&lt;/FONT&gt;&lt;/A&gt;]&amp;nbsp; &lt;/P&gt;
&lt;P&gt;Conflicts&amp;nbsp;are very common when &lt;A href="http://en.wikipedia.org/wiki/Concurrency_(computer_science)" target=_blank&gt;concurrently&lt;/A&gt; accessing the same data.&lt;/P&gt;
&lt;H1&gt;Conflicts in concurrent data access&lt;/H1&gt;
&lt;P&gt;The following code presents the concurrent conflict scenario:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Action&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: blue"&gt;int&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #2b91af"&gt;Action&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;Category&lt;/SPAN&gt;&amp;gt;&amp;gt; updateCategory = (id, updater) =&amp;gt;
    {
        &lt;SPAN style="COLOR: blue"&gt;using &lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;NorthwindDataContext &lt;/SPAN&gt;database = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;NorthwindDataContext&lt;/SPAN&gt;())
        {
            &lt;SPAN style="COLOR: #2b91af"&gt;Category &lt;/SPAN&gt;category = database.Categories
                                        .Single(item =&amp;gt; item.CategoryID == id);

            &lt;SPAN style="COLOR: #2b91af"&gt;Thread&lt;/SPAN&gt;.Sleep(4000);

            updater(category);
            &lt;SPAN style="COLOR: green"&gt;// database.SubmitChanges() invokes:
            &lt;/SPAN&gt;database.SubmitChanges(&lt;SPAN style="COLOR: #2b91af"&gt;ConflictMode&lt;/SPAN&gt;.FailOnFirstConflict);
        }
    };

&lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Thread&lt;/SPAN&gt;(() =&amp;gt; updateCategory(1, category =&amp;gt; category.CategoryName = &lt;SPAN style="COLOR: #a31515"&gt;"Thread 1"&lt;/SPAN&gt;)).Start();

&lt;SPAN style="COLOR: #2b91af"&gt;Thread&lt;/SPAN&gt;.Sleep(2000);

&lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Thread&lt;/SPAN&gt;(() =&amp;gt; updateCategory(1, category =&amp;gt; category.CategoryName = &lt;SPAN style="COLOR: #a31515"&gt;"Thread 2"&lt;/SPAN&gt;)).Start();&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;Here 2 threads are accessing the same category. This is the order of the executions:&lt;/P&gt;
&lt;TABLE border=0 cellSpacing=0 cellPadding=2 width=662&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=127&gt;Time (second)&lt;/TD&gt;
&lt;TD vAlign=top width=149&gt;Thread 1&lt;/TD&gt;
&lt;TD vAlign=top width=178&gt;Thread 2&lt;/TD&gt;
&lt;TD vAlign=top width=206&gt;[CategoryName] database value&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=127&gt;0 (Thread 1 reads)&lt;/TD&gt;
&lt;TD vAlign=top width=149&gt;Retrieves “Beverages”&lt;/TD&gt;
&lt;TD vAlign=top width=178&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD vAlign=top width=206&gt;“Beverages”&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=127&gt;2 (Thread 2 reads)&lt;/TD&gt;
&lt;TD vAlign=top width=149&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD vAlign=top width=178&gt;Retrieves “Beverages”&lt;/TD&gt;
&lt;TD vAlign=top width=206&gt;“Beverages”&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=127&gt;4 (Thread 1 writes)&lt;/TD&gt;
&lt;TD vAlign=top width=149&gt;updates “Beverages” to “Thread 1”&lt;/TD&gt;
&lt;TD vAlign=top width=178&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD vAlign=top width=206&gt;“Thread 1”&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=127&gt;6 (Thread 2 writes)&lt;/TD&gt;
&lt;TD vAlign=top width=149&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD vAlign=top width=178&gt;&lt;U&gt;Should update “Beverages” to “Thread 2”&lt;/U&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=206&gt;&lt;U&gt;[CategoryName] is no longer “Beverages”&lt;/U&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;When the later started thread (thread 2) tries to submit the change, the conflict occurs, and DataContext.SubmitChanges() throws a ChangeConflictException:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;Row not found or changed.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;H1&gt;Optimistic concurrency control&lt;/H1&gt;
&lt;P&gt;The &lt;A href="http://en.wikipedia.org/wiki/Concurrency_control" target=_blank&gt;concurrency control&lt;/A&gt; tactic of LINQ to SQL is &lt;A href="http://en.wikipedia.org/wiki/Optimistic_concurrency_control" target=_blank&gt;optimistic&lt;/A&gt;, which means LINQ to SQL checks the status of data instead of locking the data (pessimistic concurrency control).&lt;/P&gt;
&lt;P&gt;This is the translated SQL from 2 threads:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: green"&gt;-- Thread 1 reads.
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;exec &lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;sp_executesql &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'SELECT [t0].[CategoryID], [t0].[CategoryName], [t0].[Description], [t0].[Picture]
FROM [dbo].[Categories] AS [t0]
WHERE [t0].[CategoryID] = @p0'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'@p0 int'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p0&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;1

&lt;SPAN style="COLOR: green"&gt;-- Thread 2 reads.
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;exec &lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;sp_executesql &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'SELECT [t0].[CategoryID], [t0].[CategoryName], [t0].[Description], [t0].[Picture]
FROM [dbo].[Categories] AS [t0]
WHERE [t0].[CategoryID] = @p0'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'@p0 int'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p0&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;1

&lt;SPAN style="COLOR: green"&gt;-- Thread 1 writes.
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;BEGIN TRANSACTION 
exec &lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;sp_executesql &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'UPDATE [dbo].[Categories]
SET [CategoryName] = @p2
WHERE ([CategoryID] = @p0) AND (&lt;U&gt;[CategoryName] = @p1&lt;/U&gt;)'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'@p0 int,@p1 nvarchar(4000),@p2 nvarchar(4000)'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p0&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;1&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p1&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'Beverages'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p2&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'Thread 1' &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;-- CategoryName has an [Column(UpdateCheck = UpdateCheck.Always)] attribute.&lt;/SPAN&gt;
&lt;SPAN style="COLOR: blue"&gt;COMMIT TRANSACTION &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;-- Updating successes.

-- Thread 2 writes.
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;BEGIN TRANSACTION 
exec &lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;sp_executesql &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'UPDATE [dbo].[Categories]
SET [CategoryName] = @p2
WHERE ([CategoryID] = @p0) AND (&lt;U&gt;[CategoryName] = @p1&lt;/U&gt;)'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'@p0 int,@p1 nvarchar(4000),@p2 nvarchar(4000)'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p0&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;1&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p1&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'Beverages'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p2&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'Thread 2' &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;-- CategoryName has an [Column(UpdateCheck = UpdateCheck.Always)] attribute.&lt;/SPAN&gt;
&lt;SPAN style="COLOR: blue"&gt;ROLLBACK TRANSACTION &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;-- Updating fails.
&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;When submitting data changes, LINQ to SQL not only uses primary key to identify the data, but also checks the original state of the column which is expected to be updated.&lt;/P&gt;
&lt;H2&gt;Update check&lt;/H2&gt;
&lt;P&gt;This original state check is specified by the [Column] attribute of entity property: &lt;/P&gt;
&lt;P&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=image border=0 alt=image src="http://weblogs.asp.net/blogs/dixin/image_14545167.png" width=278 height=480 mce_src="http://weblogs.asp.net/blogs/dixin/image_14545167.png"&gt;&lt;/P&gt;
&lt;P&gt;If ColumnAttribute.UpdateCheck is not specified:&lt;/P&gt;&lt;PRE class=code&gt;[&lt;SPAN style="COLOR: #2b91af"&gt;Column&lt;/SPAN&gt;(Storage = &lt;SPAN style="COLOR: #a31515"&gt;"_CategoryName"&lt;/SPAN&gt;, DbType = &lt;SPAN style="COLOR: #a31515"&gt;"NVarChar(15) NOT NULL"&lt;/SPAN&gt;, CanBeNull = &lt;SPAN style="COLOR: blue"&gt;false&lt;/SPAN&gt;)]
&lt;SPAN style="COLOR: blue"&gt;public string &lt;/SPAN&gt;CategoryName
{
}&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;then it will have a default value: UpdateCheck.Always:&lt;/P&gt;&lt;PRE class=code&gt;[&lt;SPAN style="COLOR: #2b91af"&gt;AttributeUsage&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;AttributeTargets&lt;/SPAN&gt;.Field | &lt;SPAN style="COLOR: #2b91af"&gt;AttributeTargets&lt;/SPAN&gt;.Property, AllowMultiple = &lt;SPAN style="COLOR: blue"&gt;false&lt;/SPAN&gt;)]
&lt;SPAN style="COLOR: blue"&gt;public sealed class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ColumnAttribute &lt;/SPAN&gt;: &lt;SPAN style="COLOR: #2b91af"&gt;DataAttribute
&lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: blue"&gt;private &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;UpdateCheck &lt;/SPAN&gt;_updateCheck = &lt;U&gt;&lt;SPAN style="COLOR: #2b91af"&gt;UpdateCheck&lt;/SPAN&gt;.Always&lt;/U&gt;;

    &lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;UpdateCheck &lt;/SPAN&gt;UpdateCheck
    {
        &lt;SPAN style="COLOR: blue"&gt;get
        &lt;/SPAN&gt;{
            &lt;SPAN style="COLOR: blue"&gt;return this&lt;/SPAN&gt;._updateCheck;
        }
        &lt;SPAN style="COLOR: blue"&gt;set
        &lt;/SPAN&gt;{
            &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;._updateCheck = &lt;SPAN style="COLOR: blue"&gt;value&lt;/SPAN&gt;;
        }
    }
}&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;H2&gt;Time stamp&lt;/H2&gt;
&lt;P&gt;In the above screenshot, there is a [Time Stamp] option in the O/R designer, which can be used when this column is of type timestamp (rowversion). To demonstrating this, add a timestamp column [Version] to the [Categories] table:&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=image border=0 alt=image src="http://weblogs.asp.net/blogs/dixin/image_2F5CFAA8.png" width=308 height=342 mce_src="http://weblogs.asp.net/blogs/dixin/image_2F5CFAA8.png"&gt; &lt;/P&gt;
&lt;P&gt;And recreate the model in O/R designer. Now this is the generated [Column] attribute:&lt;/P&gt;&lt;PRE class=code&gt;[&lt;SPAN style="COLOR: #2b91af"&gt;Column&lt;/SPAN&gt;(Storage = &lt;SPAN style="COLOR: #a31515"&gt;"_Version"&lt;/SPAN&gt;, &lt;U&gt;AutoSync = &lt;SPAN style="COLOR: #2b91af"&gt;AutoSync&lt;/SPAN&gt;.Always&lt;/U&gt;, DbType = &lt;SPAN style="COLOR: #a31515"&gt;"&lt;U&gt;rowversion&lt;/U&gt; NOT NULL"&lt;/SPAN&gt;, 
    CanBeNull = &lt;SPAN style="COLOR: blue"&gt;false&lt;/SPAN&gt;, &lt;U&gt;IsDbGenerated = &lt;SPAN style="COLOR: blue"&gt;true&lt;/SPAN&gt;&lt;/U&gt;, &lt;U&gt;IsVersion = &lt;SPAN style="COLOR: blue"&gt;true&lt;/SPAN&gt;&lt;/U&gt;, UpdateCheck = &lt;SPAN style="COLOR: #2b91af"&gt;UpdateCheck&lt;/SPAN&gt;.Never)]
&lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Binary &lt;/SPAN&gt;Version
{
}&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;Now LINQ to SQL always checks the [Version] column instead of [CategoryName] column. So when rerunning the above code, the translated SQL is different:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: green"&gt;-- Thread 1 reads.
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;exec &lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;sp_executesql &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'SELECT [t0].[CategoryID], [t0].[CategoryName], [t0].[Description], [t0].[Picture], [t0].&lt;U&gt;[Version]&lt;/U&gt;
FROM [dbo].[Categories] AS [t0]
WHERE [t0].[CategoryID] = @p0'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'@p0 int'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p0&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;1

&lt;SPAN style="COLOR: green"&gt;-- Thread 2 reads.
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;exec &lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;sp_executesql &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'SELECT [t0].[CategoryID], [t0].[CategoryName], [t0].[Description], [t0].[Picture], [t0].&lt;U&gt;[Version]
&lt;/U&gt;FROM [dbo].[Categories] AS [t0]
WHERE [t0].[CategoryID] = @p0'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'@p0 int'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p0&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;1

&lt;SPAN style="COLOR: green"&gt;-- Thread 1 writes.
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;BEGIN TRANSACTION 
&lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;-- Checks time stamp.
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;exec &lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;sp_executesql &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'UPDATE [dbo].[Categories]
SET [CategoryName] = @p2
WHERE ([CategoryID] = @p0) AND (&lt;U&gt;[Version] = @p1&lt;/U&gt;)

SELECT [t1].&lt;U&gt;[Version]&lt;/U&gt;
FROM [dbo].[Categories] AS [t1]
WHERE ((@@ROWCOUNT) &amp;gt; 0) AND ([t1].[CategoryID] = @p3)'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'@p0 int,@p1 timestamp,@p2 nvarchar(4000),@p3 int'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p0&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;1&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p1&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;0x0000000000000479&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p2&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'Thread 1'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p3&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;1
&lt;SPAN style="COLOR: green"&gt;-- SELECT for [Column(AutoSync = AutoSync.Always)]
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;COMMIT TRANSACTION &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;-- Updating successes.

-- Thread 2 writes.
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;BEGIN TRANSACTION 
&lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;-- Checks time stamp.
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;exec &lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;sp_executesql &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'UPDATE [dbo].[Categories]
SET [CategoryName] = @p2
WHERE ([CategoryID] = @p0) AND (&lt;U&gt;[Version] = @p1&lt;/U&gt;)

SELECT [t1].&lt;U&gt;[Version]&lt;/U&gt;
FROM [dbo].[Categories] AS [t1]
WHERE ((@@ROWCOUNT) &amp;gt; 0) AND ([t1].[CategoryID] = @p3)'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'@p0 int,@p1 timestamp,@p2 nvarchar(4000),@p3 int'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p0&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;1&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p1&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;0x0000000000000479&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p2&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'Thread 2'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p3&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;1
&lt;SPAN style="COLOR: green"&gt;-- SELECT for [Column(AutoSync = AutoSync.Always)]
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;ROLLBACK TRANSACTION &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;-- Updating fails.
&lt;/SPAN&gt;&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;H1&gt;Handle ChangeConflictException&lt;/H1&gt;
&lt;P&gt;When concurrent conflict occurs, SubmitChanges() rollbacks the TRANSACTION, then throws a ChangeConflictException exception.&lt;/P&gt;
&lt;P&gt;So if the caller of DataContext.SubmitChanges() knows how to resolve the conflict, it can detects conflict by handling ChangeConflictException . &lt;/P&gt;
&lt;H2&gt;Merge changes to resolve conflict&lt;/H2&gt;
&lt;P&gt;For example, a common tactic is to merge the changes into database:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Action&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: blue"&gt;int&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #2b91af"&gt;Action&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;Category&lt;/SPAN&gt;&amp;gt;&amp;gt; updateCategory = (id, updater) =&amp;gt;
    {
        &lt;SPAN style="COLOR: blue"&gt;using &lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;NorthwindDataContext &lt;/SPAN&gt;database = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;NorthwindDataContext&lt;/SPAN&gt;())
        {
            &lt;SPAN style="COLOR: #2b91af"&gt;Category &lt;/SPAN&gt;category = database.Categories
                                        .Single(item =&amp;gt; item.CategoryID == id);

            &lt;SPAN style="COLOR: #2b91af"&gt;Thread&lt;/SPAN&gt;.Sleep(4000);

            updater(category);
            &lt;SPAN style="COLOR: blue"&gt;try
            &lt;/SPAN&gt;{
                &lt;SPAN style="COLOR: green"&gt;// All data changes will be tried before rollback.
                &lt;/SPAN&gt;database.SubmitChanges(&lt;SPAN style="COLOR: #2b91af"&gt;ConflictMode&lt;/SPAN&gt;.ContinueOnConflict);
                &lt;SPAN style="COLOR: green"&gt;// Now all conflicts are stored in DataContext.ChangeConflicts.
            &lt;/SPAN&gt;}
            &lt;SPAN style="COLOR: blue"&gt;catch &lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;ChangeConflictException&lt;/SPAN&gt;)
            {
                &lt;SPAN style="COLOR: blue"&gt;foreach &lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;ObjectChangeConflict &lt;/SPAN&gt;conflict &lt;SPAN style="COLOR: blue"&gt;in &lt;/SPAN&gt;database.ChangeConflicts)
                {
                    &lt;SPAN style="COLOR: #2b91af"&gt;Console&lt;/SPAN&gt;.WriteLine(
                        &lt;SPAN style="COLOR: #a31515"&gt;"Conflicted row: ID = {0}."&lt;/SPAN&gt;,
                        (conflict.Object &lt;SPAN style="COLOR: blue"&gt;as &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Category&lt;/SPAN&gt;).CategoryID);

                    &lt;SPAN style="COLOR: blue"&gt;foreach &lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;MemberChangeConflict &lt;/SPAN&gt;member &lt;SPAN style="COLOR: blue"&gt;in &lt;/SPAN&gt;conflict.MemberConflicts)
                    {
                        &lt;SPAN style="COLOR: #2b91af"&gt;Console&lt;/SPAN&gt;.WriteLine(
                            &lt;SPAN style="COLOR: #a31515"&gt;"[{0}] column is expected to be '{1}' in database, but it is not."&lt;/SPAN&gt;,
                            member.Member.Name,
                            member.CurrentValue);
                    }

                    conflict.&lt;U&gt;Resolve&lt;/U&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;RefreshMode&lt;/SPAN&gt;.KeepChanges); &lt;SPAN style="COLOR: green"&gt;// Queries row to merge changes.
                    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Console&lt;/SPAN&gt;.WriteLine(&lt;SPAN style="COLOR: #a31515"&gt;"Merged changes to row: {0}."&lt;/SPAN&gt;, conflict.IsResolved);
                }

                &lt;SPAN style="COLOR: green"&gt;// Submits again by merging changes.
                &lt;/SPAN&gt;database.SubmitChanges();
            }
        }
    };

&lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Thread&lt;/SPAN&gt;(() =&amp;gt; updateCategory(1, category =&amp;gt; category.&lt;U&gt;CategoryName&lt;/U&gt; = &lt;SPAN style="COLOR: #a31515"&gt;"Thread 1"&lt;/SPAN&gt;)).Start();

&lt;SPAN style="COLOR: #2b91af"&gt;Thread&lt;/SPAN&gt;.Sleep(2000);

&lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Thread&lt;/SPAN&gt;(() =&amp;gt; updateCategory(1, category =&amp;gt; category.&lt;U&gt;Description&lt;/U&gt; = &lt;SPAN style="COLOR: #a31515"&gt;"Thread 2"&lt;/SPAN&gt;)).Start();&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;Running this refined code will print:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;Conflicted row: ID = 1. &lt;BR&gt;[CategoryName] column is expected to be 'Beverages' in database, but it is not. &lt;BR&gt;Merged changes to row: True.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;This is the order of the executions:&lt;/P&gt;
&lt;TABLE border=0 cellSpacing=0 cellPadding=2 width=713&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=99&gt;Time (second)&lt;/TD&gt;
&lt;TD vAlign=top width=185&gt;Thread 1&lt;/TD&gt;
&lt;TD vAlign=top width=174&gt;Thread 2&lt;/TD&gt;
&lt;TD vAlign=top width=106&gt;[CategoryName] &lt;/TD&gt;
&lt;TD vAlign=top width=147&gt;[Description] &lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=99&gt;0 &lt;/TD&gt;
&lt;TD vAlign=top width=185&gt;Retrieves “Beverages” for [CategoryName].&lt;/TD&gt;
&lt;TD vAlign=top width=174&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD vAlign=top width=106&gt;“Beverages”&lt;/TD&gt;
&lt;TD vAlign=top width=147&gt;“Soft drinks, coffees, teas, beers, and ales”&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=99&gt;2 &lt;/TD&gt;
&lt;TD vAlign=top width=185&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD vAlign=top width=174&gt;Retrieves “Beverages” for [CategoryName].&lt;/TD&gt;
&lt;TD vAlign=top width=106&gt;“Beverages”&lt;/TD&gt;
&lt;TD vAlign=top width=147&gt;“Soft drinks, coffees, teas, beers, and ales”&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=99&gt;4 &lt;/TD&gt;
&lt;TD vAlign=top width=185&gt;Checks whether [CategoryName] is “Beverages”, and updates [CategoryName].&lt;/TD&gt;
&lt;TD vAlign=top width=174&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD vAlign=top width=106&gt;“Thread 1”&lt;/TD&gt;
&lt;TD vAlign=top width=147&gt;“Soft drinks, coffees, teas, beers, and ales”&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top rowSpan=3 width=99&gt;6 &lt;/TD&gt;
&lt;TD vAlign=top rowSpan=3 width=185&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD vAlign=top width=174&gt;Checks whether [CategoryName] is “Beverages”.&lt;/TD&gt;
&lt;TD vAlign=top width=106&gt;“Thread 1”&lt;/TD&gt;
&lt;TD vAlign=top width=147&gt;“Soft drinks, coffees, teas, beers, and ales”&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=174&gt;Retrieves “Thread1” for [CategoryName]&lt;/TD&gt;
&lt;TD vAlign=top width=106&gt;“Thread 1”&lt;/TD&gt;
&lt;TD vAlign=top width=147&gt;“Soft drinks, coffees, teas, beers, and ales”&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=174&gt;Checks whether [CategoryName] is “Thread 1”., and updates [Description].&lt;/TD&gt;
&lt;TD vAlign=top width=106&gt;“Thread 1”&lt;/TD&gt;
&lt;TD vAlign=top width=147&gt;“Thread 2”&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;Please notice that, to merge the changes, database must be queried.&lt;/P&gt;
&lt;P&gt;This is the entire translated SQL:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: green"&gt;-- Thread 1 reads.
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;exec &lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;sp_executesql &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'SELECT [t0].[CategoryID], [t0].[CategoryName], [t0].[Description], [t0].[Picture]
FROM [dbo].[Categories] AS [t0]
WHERE [t0].[CategoryID] = @p0'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'@p0 int'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p0&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;1

&lt;SPAN style="COLOR: green"&gt;-- Thread 2 reads.
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;exec &lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;sp_executesql &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'SELECT [t0].[CategoryID], [t0].[CategoryName], [t0].[Description], [t0].[Picture]
FROM [dbo].[Categories] AS [t0]
WHERE [t0].[CategoryID] = @p0'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'@p0 int'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p0&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;1

&lt;SPAN style="COLOR: green"&gt;-- Thread 1 writes.
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;BEGIN TRANSACTION 
exec &lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;sp_executesql &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'UPDATE [dbo].[Categories]
SET [CategoryName] = @p2
WHERE ([CategoryID] = @p0) AND ([CategoryName] = @p1)'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'@p0 int,@p1 nvarchar(4000),@p2 nvarchar(4000)'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p0&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;1&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p1&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'Beverages'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p2&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'Thread 1' &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;-- CategoryName has an [Column(UpdateCheck = UpdateCheck.Always)] attribute.
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;COMMIT TRANSACTION &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;-- Updating successes.

-- Thread 2 writes.
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;BEGIN TRANSACTION 
exec &lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;sp_executesql &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'UPDATE [dbo].[Categories]
SET [Description] = @p2
WHERE ([CategoryID] = @p0) AND ([CategoryName] = @p1)'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'@p0 int,@p1 nvarchar(4000),@p2 ntext'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p0&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;1&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p1&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'Beverages'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p2&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'Thread 2' &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;-- CategoryName has an [Column(UpdateCheck = UpdateCheck.Always)] attribute.
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;ROLLBACK TRANSACTION &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;-- Updating fails.

-- Thread 2 reads data to merge changes.
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;exec &lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;sp_executesql &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'SELECT [t0].[CategoryID], [t0].[CategoryName], [t0].[Description], [t0].[Picture]
FROM [dbo].[Categories] AS [t0]
WHERE [t0].[CategoryID] = @p0'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'@p0 int'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p0&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;1

&lt;SPAN style="COLOR: green"&gt;-- Thread 2 writes again.
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;BEGIN TRANSACTION 
exec &lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;sp_executesql &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'UPDATE [dbo].[Categories]
SET [CategoryName] = @p2, [Description] = @p3
WHERE ([CategoryID] = @p0) AND ([CategoryName] = @p1)'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'@p0 int,@p1 nvarchar(4000),@p2 nvarchar(4000),@p3 ntext'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p0&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;1&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p1&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'Thread 1'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p2&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'Thread 1'&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;@p3&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;N'Thread 2'
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;COMMIT TRANSACTION &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;-- Updating successes.
&lt;/SPAN&gt;&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;To resolve conflicts, an easier way is just invoking ChangeConflictCollection.ResolveAll():&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;catch &lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;ChangeConflictException&lt;/SPAN&gt;)
{
&lt;SPAN style="COLOR: green"&gt;    &lt;/SPAN&gt;database.ChangeConflicts.ResolveAll(&lt;SPAN style="COLOR: #2b91af"&gt;RefreshMode&lt;/SPAN&gt;.KeepChanges);&lt;SPAN style="COLOR: green"&gt;
    &lt;/SPAN&gt;database.SubmitChanges();
}&lt;/PRE&gt;
&lt;H1&gt;More about concurrency&lt;/H1&gt;
&lt;P&gt;Because this is a LINQ / functional programming series, not a SQL / database series, this post only gives a brief explanation about how LINQ to SQL controls concurrent conflict. please check &lt;A href="http://msdn.microsoft.com/en-us/library/bb399373.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/bb399373.aspx"&gt;MSDN&lt;/A&gt; and Wikipedia for further topics, like &lt;A href="http://en.wikipedia.org/wiki/Concurrency_(computer_science)" target=_blank mce_href="http://en.wikipedia.org/wiki/Concurrency_(computer_science)"&gt;concurrency&lt;/A&gt;, &lt;A href="http://en.wikipedia.org/wiki/Concurrency_control" target=_blank mce_href="http://en.wikipedia.org/wiki/Concurrency_control"&gt;concurrency control&lt;/A&gt;, &lt;A href="http://en.wikipedia.org/wiki/Optimistic_concurrency_control" target=_blank mce_href="http://en.wikipedia.org/wiki/Optimistic_concurrency_control"&gt;optimistic concurrency control&lt;/A&gt;, &lt;A href="http://en.wikipedia.org/wiki/Timestamp-based_concurrency_control" target=_blank mce_href="http://en.wikipedia.org/wiki/Timestamp-based_concurrency_control"&gt;timestamp-based concurrency control&lt;/A&gt;, &lt;A href="http://msdn.microsoft.com/en-us/library/aa213068(v=SQL.80).aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/aa213068(v=SQL.80).aspx"&gt;SQL Server transactions&lt;/A&gt;, &lt;A href="http://msdn.microsoft.com/en-us/library/aa213039(SQL.80).aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/aa213039(SQL.80).aspx"&gt;SQL Server locking&lt;/A&gt;, &lt;A href="http://msdn.microsoft.com/en-us/library/aa213034(SQL.80).aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/aa213034(SQL.80).aspx"&gt;SQL Server isolation levels&lt;/A&gt;, &lt;A href="http://msdn.microsoft.com/en-us/library/cc917674.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/cc917674.aspx"&gt;SQL Server row level versioning&lt;/A&gt;, etc.&lt;/P&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=7460505" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/dixin/archive/tags/.NET/default.aspx">.NET</category><category domain="http://weblogs.asp.net/dixin/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://weblogs.asp.net/dixin/archive/tags/Visual+Studio/default.aspx">Visual Studio</category><category domain="http://weblogs.asp.net/dixin/archive/tags/LINQ/default.aspx">LINQ</category><category domain="http://weblogs.asp.net/dixin/archive/tags/SQL+Server/default.aspx">SQL Server</category><category domain="http://weblogs.asp.net/dixin/archive/tags/TSQL/default.aspx">TSQL</category><category domain="http://weblogs.asp.net/dixin/archive/tags/LINQ+via+C_2300_+Series/default.aspx">LINQ via C# Series</category><category domain="http://weblogs.asp.net/dixin/archive/tags/LINQ+to+SQL/default.aspx">LINQ to SQL</category></item></channel></rss>
