<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://msmvps.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Omar AL Zabir blog on ASP.NET Ajax and .NET 3.5 : .net</title><link>http://msmvps.com/blogs/omar/archive/tags/.net/default.aspx</link><description>Tags: .net</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP2 (Build: 40407.4157)</generator><item><title>Simple way to cache objects and collections for greater performance and scalability</title><link>http://msmvps.com/blogs/omar/archive/2009/11/01/simple-way-to-cache-objects-and-collections-for-greater-performance-and-scalability.aspx</link><pubDate>Sun, 01 Nov 2009 16:41:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1736807</guid><dc:creator>omar</dc:creator><slash:comments>7</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/omar/rsscomments.aspx?PostID=1736807</wfw:commentRss><comments>http://msmvps.com/blogs/omar/archive/2009/11/01/simple-way-to-cache-objects-and-collections-for-greater-performance-and-scalability.aspx#comments</comments><description>&lt;p&gt;Caching of frequently used data greatly increases the scalability of your application since you can avoid repeated queries on database, file system or to webservices. When objects are cached, it can be retrieved from the cache which is lot faster and more scalable than loading from database, file or web service. However, implementing caching is tricky and monotonous when you have to do it for many classes. Your data access layer gets a whole lot of code that deals with caching objects and collection, updating cache when objects change or get deleted, expire collections when a contained object changes or gets deleted and so on. The more code you write, the more maintenance overhead you add. Here I will show you how you can make the caching a lot easier using Linq to SQL and my library &lt;a title="Fluent way to add Aspect in your code" href="http://code.google.com/p/aspectf/"&gt;AspectF&lt;/a&gt;. It’s a library that helps you get rid of thousands of lines of repeated code from a medium sized project and eliminates plumbing (logging, error handling, retrying etc) type code completely.&lt;/p&gt;  &lt;p&gt;Here’s an example how caching significantly improves the performance and scalabitlity of applications. Dropthings – my open source Web 2.0 AJAX portal, without caching can only serve about 11 request/sec with 10 concurrent users on a dual core 64 bit PC. Here data is loaded from database as well as from external sources. Avg page response time is 1.44 sec.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar.metablogapi/4606.LoadTestWithoutCache_5F00_507E9888.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="Load Test Without Cache" border="0" alt="Load Test Without Cache" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar.metablogapi/0003.LoadTestWithoutCache_5F00_thumb_5F00_4D790E08.png" width="557" height="364" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;After implementing caching, it became significantly faster, around &lt;strong&gt;32 requests/sec&lt;/strong&gt;. Page load time decreased significantly as well to &lt;strong&gt;0.41 sec&lt;/strong&gt; only. During the load test, CPU utilization was around 60%.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar.metablogapi/0410.LoadTestwithinmemorycache_5F00_33E15B0E.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="Load Test with in memory cache" border="0" alt="Load Test with in memory cache" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar.metablogapi/6761.LoadTestwithinmemorycache_5F00_thumb_5F00_7F6088C5.png" width="598" height="411" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;It shows clearly the significant difference it can make to your application. If you are suffering from poor page load performance and high CPU or disk activity on your database and application server, then caching Top 5 most frequently used objects in your application will solve that problem right away. It’s a quick win to make your application a lot faster than doing complex re-engineering in your application.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Common approaches to caching objects and collections&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Sometimes the caching can be simple, for example caching a single object which does not belong to a collection and does not have child collections that are cached separately. In such case, you write simple code like this:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Is the object being requested already in cache?      &lt;ul&gt;       &lt;li&gt;Yes, then serve it from cache. &lt;/li&gt;        &lt;li&gt;No, then load it from database and then cache it. &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;On the other hand, when you are dealing with cached collection where each item in the collection is also cached separately, then the caching logic is not so simple. For example, say you have cached a &lt;code&gt;User&lt;/code&gt; collection. But each &lt;code&gt;User&lt;/code&gt; object is also cached separately because you need to load individual &lt;code&gt;User&lt;/code&gt; objects frequently. Then the caching logic gets more complicated:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Is the collection being requested already in cache?      &lt;ul&gt;       &lt;li&gt;Yes. Get the collection. For each object in the collection:          &lt;ul&gt;           &lt;li&gt;Is that object individually available in cache?              &lt;ul&gt;               &lt;li&gt;Yes, get the individual object from cache. Update it in the collection. &lt;/li&gt;                &lt;li&gt;No, discard the whole collection from cache. Go to next step: &lt;/li&gt;             &lt;/ul&gt;           &lt;/li&gt;         &lt;/ul&gt;       &lt;/li&gt;        &lt;li&gt;No. Load the collection from source (eg database) and cache each item in the collection separately. Then cache the collection. &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;You might be thinking why do we need to read each individual item from cache and why do we need to cache each item in collection separarely when the whole collection is already in cache? There are two scenarios you need to address when you cache a collection and individual items in that collection are also cached separately:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;An individual item has been updated and the updated item is in cache. But the collection, which contains all those individual items, has not been refreshed. So, if you get the collection from cache and return as it is, you will get stale individual items inside that collection. This is why each item needs to be retrieved from cache separately. &lt;/li&gt;    &lt;li&gt;An item in the collection may have been force expired in cache. For ex, something changed in the object or the object has been deleted. So, you expired it in cache so that on next retrieval it comes from database. If you load the collection from cache only, then the collection will contain the stale object. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;If you are doing it the conventional way, you will be writing a lot of repeated code in your data access layer. For example, say you are loading a &lt;code&gt;Page&lt;/code&gt; collection that belongs to a user. If you want to cache the collection of &lt;code&gt;Page&lt;/code&gt; for a user as well as cache individual &lt;code&gt;Page&lt;/code&gt; objects so that each &lt;code&gt;Page&lt;/code&gt; can be retrieved from Cache directly. Then you need to write code like this:&lt;/p&gt;  &lt;pre class="dark"&gt;&lt;span style="background:#2a2a2a;color:#eaeaac;"&gt;public &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#f0dfaf;"&gt;List&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#f0dfaf;"&gt;Page&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;&amp;gt; &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;GetPagesOfUserOldSchool&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#2b91af;"&gt;Guid &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;userGuid&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;)
{
    &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#2b91af;"&gt;ICache &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;cache &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#f0dfaf;"&gt;Services&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;Get&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#2b91af;"&gt;ICache&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;&amp;gt;();
    &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#eaeaac;"&gt;bool &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;isCacheStale &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#eaeaac;"&gt;false&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;;
    &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#eaeaac;"&gt;string &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;cacheKey &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#f0dfaf;"&gt;CacheSetup&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#f0dfaf;"&gt;CacheKeys&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;PagesOfUser&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;userGuid&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;);
    &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#eaeaac;"&gt;var &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;cachedPages &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;cache&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;Get&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;cacheKey&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;) &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#eaeaac;"&gt;as &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#f0dfaf;"&gt;List&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#f0dfaf;"&gt;Page&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;&amp;gt;;
    &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#eaeaac;"&gt;if &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;cachedPages &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;!= &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#eaeaac;"&gt;null&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;)
    {
        &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#eaeaac;"&gt;var &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;resultantPages &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#eaeaac;"&gt;new &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#f0dfaf;"&gt;List&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#f0dfaf;"&gt;Page&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;&amp;gt;();
        &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#7f9f7f;"&gt;// If each item in the collection is no longer in cache, invalidate the collection
        // and load again.
        &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#eaeaac;"&gt;foreach &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#f0dfaf;"&gt;Page &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;cachedPage &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#eaeaac;"&gt;in &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;cachedPages&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;)
        {
            &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#eaeaac;"&gt;var &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;individualPageInCache &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;cache&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;Get&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#f0dfaf;"&gt;CacheSetup&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#f0dfaf;"&gt;CacheKeys&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;PageId&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;cachedPage&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;ID&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;)) &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#eaeaac;"&gt;as &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#f0dfaf;"&gt;Page&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;;
            &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#eaeaac;"&gt;if &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#eaeaac;"&gt;null &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;== &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;individualPageInCache&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;)
            {
                &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#7f9f7f;"&gt;// Some item is missing in cache. So, the collection is stale. 
                &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;isCacheStale &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#eaeaac;"&gt;true&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;;
            }
            &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#eaeaac;"&gt;else
            &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;{
                &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;resultantPages&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;Add&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;individualPageInCache&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;);
            }
        }

        &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;cachedPages &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;resultantPages&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;;
    }

    &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#eaeaac;"&gt;if &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;isCacheStale&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;)
    {
        &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#7f9f7f;"&gt;// Collection not cached. Need to load collection from database and then cache it.
        &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#eaeaac;"&gt;var &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;pagesOfUser &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;_database&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;GetList&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#f0dfaf;"&gt;Page&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#2b91af;"&gt;Guid&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;&amp;gt;(...&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;);
        &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;pagesOfUser&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;Each&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;page &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;=&amp;gt;
        {
            &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;page&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;Detach&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;();
            &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;cache&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;Add&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#f0dfaf;"&gt;CacheSetup&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#f0dfaf;"&gt;CacheKeys&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;PageId&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;page&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;ID&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;), &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;page&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;);
        });
        &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;cache&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;Add&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;cacheKey&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;pagesOfUser&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;);
        &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#eaeaac;"&gt;return &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;pagesOfUser&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;;
    }
    &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#eaeaac;"&gt;else
    &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;{
        &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#eaeaac;"&gt;return &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;cachedPages&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;;
    }
}&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"&gt;&lt;/a&gt;

&lt;p&gt;Imagine writing this kind of code over and over again for each and every entity that you want to cache. This becomes a maintenace nightmare as your project grows.&lt;/p&gt;

&lt;p&gt;Here’s how you could do it using &lt;a title="Fluent way to add Aspect in your code" href="http://code.google.com/p/aspectf/"&gt;AspectF&lt;/a&gt;:&lt;/p&gt;

&lt;pre class="dark"&gt;&lt;span style="background:#2a2a2a;color:#eaeaac;"&gt;public &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#f0dfaf;"&gt;List&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#f0dfaf;"&gt;Page&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;&amp;gt; &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;GetPagesOfUser&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#2b91af;"&gt;Guid &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;userGuid&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;)
{
    &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#eaeaac;"&gt;return &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#f0dfaf;"&gt;AspectF&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;Define
        &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;CacheList&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#f0dfaf;"&gt;Page&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#f0dfaf;"&gt;List&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#f0dfaf;"&gt;Page&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;&amp;gt;&amp;gt;(&lt;span style="background:#2a2a2a;color:#f0dfaf;"&gt;Services&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;Get&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#2b91af;"&gt;ICache&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;&amp;gt;()&lt;/span&gt;&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;, &lt;br /&gt;&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#f0dfaf;"&gt;                     CacheSetup&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#f0dfaf;"&gt;CacheKeys&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;PagesOfUser&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;userGuid&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;), &lt;br /&gt;&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;                     page &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#f0dfaf;"&gt;CacheSetup&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#f0dfaf;"&gt;CacheKeys&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;PageId&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;page&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;ID&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;))
        .&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;Return&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#f0dfaf;"&gt;List&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#f0dfaf;"&gt;Page&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;&amp;gt;&amp;gt;(() =&amp;gt; 
            &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;_database&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;GetList&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#f0dfaf;"&gt;Page&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#2b91af;"&gt;Guid&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;&amp;gt;(&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#f0dfaf;"&gt;...&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;).&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;Select&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;p &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;p&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;Detach&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;()).&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dfdfbf;"&gt;ToList&lt;/span&gt;&lt;span style="background:#2a2a2a;color:#dcdccc;"&gt;());
}
&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Instead of 42 lines of code, you can do it in 5 lines!&lt;/p&gt;

&lt;p&gt;Read my article &lt;a title="Simple way to cache objects and collections for greater performance and scalability" href="http://www.codeproject.com/KB/web-cache/easycaching.aspx"&gt;Simple way to cache objects and collections for greater performance and scalability&lt;/a&gt; on CodeProject and learn:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Caching Linq to SQL entities &lt;/li&gt;

  &lt;li&gt;Handling update and delete scenarios&lt;/li&gt;

  &lt;li&gt;Expiring dependent objects and collections in cache&lt;/li&gt;

  &lt;li&gt;Handling objects that’s cached with multiple keys&lt;/li&gt;

  &lt;li&gt;Avoid database query optimizations when you cache sets of data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Enjoy. Don’t forget to vote for me!&lt;/p&gt;&lt;div class="wlWriterHeaderFooter" style="margin:0px;padding:0px 0px 0px 0px;"&gt;&lt;a href="http://dotnetburner.com/vote?url=http%3a%2f%2fmsmvps.com%2fblogs%2fomar%2farchive%2f2009%2f11%2f01%2fsimple-way-to-cache-objects-and-collections-for-greater-performance-and-scalability.aspx" rev="vote-for"&gt;&lt;img src="http://dotnetburner.com/image.axd?url=http%3a%2f%2fmsmvps.com%2fblogs%2fomar%2farchive%2f2009%2f11%2f01%2fsimple-way-to-cache-objects-and-collections-for-greater-performance-and-scalability.aspx" style="border:0px;" alt="Burn!" /&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fmsmvps.com%2fblogs%2fomar%2farchive%2f2009%2f11%2f01%2fsimple-way-to-cache-objects-and-collections-for-greater-performance-and-scalability.aspx" rev="vote-for"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fmsmvps.com%2fblogs%2fomar%2farchive%2f2009%2f11%2f01%2fsimple-way-to-cache-objects-and-collections-for-greater-performance-and-scalability.aspx" style="border:0px;" alt="kick it" /&gt;&lt;/a&gt;&amp;nbsp;&lt;a rev="vote-for" href="http://dotnetshoutout.com/Submit?url=http%3a%2f%2fmsmvps.com%2fblogs%2fomar%2farchive%2f2009%2f11%2f01%2fsimple-way-to-cache-objects-and-collections-for-greater-performance-and-scalability.aspx"&gt;&lt;img alt="Shout it" src="http://dotnetshoutout.com/image.axd?url=http%3a%2f%2fmsmvps.com%2fblogs%2fomar%2farchive%2f2009%2f11%2f01%2fsimple-way-to-cache-objects-and-collections-for-greater-performance-and-scalability.aspx" style="border:0px;" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1736807" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/performance/default.aspx">performance</category><category domain="http://msmvps.com/blogs/omar/archive/tags/linq/default.aspx">linq</category><category domain="http://msmvps.com/blogs/omar/archive/tags/.net/default.aspx">.net</category></item><item><title>Web 2.0 AJAX Portal using jQuery, ASP.NET 3.5, Silverlight, Linq to SQL, WF and Unity</title><link>http://msmvps.com/blogs/omar/archive/2009/04/08/web-2-0-ajax-portal-using-jquery-asp-net-3-5-silverlight-linq-to-sql-wf-and-unity.aspx</link><pubDate>Wed, 08 Apr 2009 18:16:22 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1685991</guid><dc:creator>omar</dc:creator><slash:comments>11</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/omar/rsscomments.aspx?PostID=1685991</wfw:commentRss><comments>http://msmvps.com/blogs/omar/archive/2009/04/08/web-2-0-ajax-portal-using-jquery-asp-net-3-5-silverlight-linq-to-sql-wf-and-unity.aspx#comments</comments><description>&lt;p&gt;&lt;a title="Dropthings Web 2.0 style AJAX portal" href="http://dropthings.omaralzabir.com" target="_blank"&gt;Dropthings&lt;/a&gt; – my &lt;a title="Dropthings - Open Source AJAX Portal" href="http://www.codeplex.com/dropthings" target="_blank"&gt;open source&lt;/a&gt; Web 2.0 Ajax Portal has gone through a technology overhauling. Previously it was built using ASP.NET AJAX, a little bit of Workflow Foundation and Linq to SQL. Now Dropthings boasts full &lt;strong&gt;jQuery&lt;/strong&gt; front-end combined with ASP.NET AJAX &lt;code&gt;UpdatePanel&lt;/code&gt;, &lt;strong&gt;Silverlight widget&lt;/strong&gt;, full &lt;strong&gt;Workflow Foundation&lt;/strong&gt; implementation on the business layer, 100% &lt;strong&gt;Linq to SQL Compiled Queries&lt;/strong&gt; on the data access layer, Dependency Injection and Inversion of Control (IoC) using &lt;strong&gt;Microsoft Enterprise Library 4.1&lt;/strong&gt; and &lt;strong&gt;Unity&lt;/strong&gt;. It also has a ASP.NET AJAX Web Test framework that makes it real easy to write Web Tests that simulates real user actions on AJAX web pages. This article will walk you through the challenges in getting these new technologies to work in an ASP.NET website and how performance, scalability, extensibility and maintainability has significantly improved by the new technologies. Dropthings has been licensed for commercial use by prominent companies including BT Business, Intel, Microsoft IS, Denmark Government portal for Citizens; Startups like Limead and many more. So, this is serious stuff! There’s a very cool open source implementation of Dropthings framework available at &lt;a title="AJAX Portal at National University of Singapore" href="http://nexus.nus.edu.sg/apicta" target="_blank"&gt;National University of Singapore&lt;/a&gt; portal.&lt;/p&gt;  &lt;p&gt;Visit: &lt;a href="http://dropthings.omaralzabir.com"&gt;http://dropthings.omaralzabir.com&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_57907290.png"&gt;&lt;img title="Dropthings AJAX Portal" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="529" alt="Dropthings AJAX Portal" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_37551A39.png" width="600" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;I have published a new article on this on CodeProject:&lt;/p&gt;  &lt;p&gt;&lt;a title="Web 2.0 AJAX Portal using jQuery, ASP.NET 3.5, Silverlight, Linq to SQL, WF and Unity" href="http://www.codeproject.com/KB/ajax/Web20Portal.aspx"&gt;http://www.codeproject.com/KB/ajax/Web20Portal.aspx&lt;/a&gt;&lt;/p&gt;  &lt;h2&gt;Get the source code&lt;/h2&gt;  &lt;p&gt;Latest source code is hosted at Google code:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://code.google.com/p/dropthings"&gt;http://code.google.com/p/dropthings&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;There’s a CodePlex site for documentation and issue tracking:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.codeplex.com/dropthings"&gt;http://www.codeplex.com/dropthings&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;You will need Visual Studio 2008 Team Suite with Service Pack 1 and Silverlight 2 SDK in order to run all the projects. If you have only Visual Studio 2008 Professional, then you will have to remove the Dropthings.Test project.&lt;/p&gt;  &lt;h2&gt;New features introduced&lt;/h2&gt;  &lt;p&gt;Dropthings new release has the following features:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Template users – you can define a user who’s pages and widgets are used as a template for new users. Whatever you put in that template user’s pages, it will be copied for every new user. Thus this is an easier way to define the default pages and widgets for new users. Similarly you can do the same for a registered user. The template users can be defined in the &lt;code&gt;web.config&lt;/code&gt;. &lt;/li&gt;    &lt;li&gt;Widget-to-Widget communication – Widgets can send message to each other. Widgets can subscribe to an Event Broker and exchange messages using a Pub-Sub pattern. &lt;/li&gt;    &lt;li&gt;WidgetZone – you can create any number of zones in any shape on the page. You can have widgets laid in horizontal layout, you can have zones on different places on the page and so on. With this zone model, you are no longer limited to the Page-Column model where you could only have N vertical columns. &lt;/li&gt;    &lt;li&gt;Role based widgets – now widgets are mapped to roles so that you can allow different users to see different widget list using &lt;code&gt;ManageWidgetPersmission.aspx.&lt;/code&gt; &lt;/li&gt;    &lt;li&gt;Role based page setup – you can define page setup for different roles. For ex, Managers see different pages and widgets than Employees. &lt;/li&gt;    &lt;li&gt;Widget maximize – you can maximize a widget to take full screen. Handy for widgets with lots of content. &lt;/li&gt;    &lt;li&gt;Free form resize – you can freely resize widgets vertically. &lt;/li&gt;    &lt;li&gt;Silverlight Widgets – You can now make widgets in Silverlight! &lt;/li&gt; &lt;/ul&gt;  &lt;h2&gt;Why the technology overhauling&lt;/h2&gt;  &lt;p&gt;Performance, Scalability, Maintainability and Extensibility – four key reasons for the overhauling. Each new technology solved one of more of these problems. &lt;/p&gt;  &lt;p&gt;First, jQuery was used to replace my personal hand-coded large amount of Javascript code that offered the client side drag &amp;amp; drop and other UI effects. jQuery already has a rich set of library for Drag &amp;amp; Drop, Animations, Event handling, cross browser javascript framework and so on. So, using jQuery means opening the door to thousands of jQuery plugins to be offered on Dropthings. This made Dropthings highly extensible on the client side. Moreover, jQuery is very light. Unlike AJAX Control Toolkit jumbo sized framework and heavy control extenders, jQuery is very lean. So, total javascript size decreased significantly resulting in improved page load time. In total, the jQuery framework, AJAX basic framework, all my stuffs are total 395KB, sweet! Performance is key; it makes or breaks a product.&lt;/p&gt;  &lt;p&gt;Secondly, Linq to SQL queries are replaced with Compiled Queries. Dropthings did not survive a load test when regular lambda expressions were used to query database. I could only reach up to 12 Req/Sec using 20 concurrent users without burning up web server CPU on a Quad Core DELL server. &lt;/p&gt;  &lt;p&gt;Thirdly, Workflow Foundation is used to build operations that require multiple Data Access Classes to perform together in a single transaction. Instead of writing large functions with many if…else conditions, for…loops, it’s better to write them in a Workflow because you can visually see the flow of execution and you can reuse Activities among different Workflows. Best of all, architects can design workflows and developers can fill-in code inside Activities. So, I could design a complex operations in a workflow without writing the real code inside Activities and then ask someone else to implement each Activity. It is like handing over a design document to developers to implement each unit module, only that here everything is strongly typed and verified by compiler. If you strictly follow Single Responsibility Principle for your Activities, which is a smart way of saying one Activity does only one and very simple task, you end up with a highly reusable and maintainable business layer and a very clean code that’s easily extensible.&lt;/p&gt;  &lt;p&gt;Fourthly, &lt;a title="Unity Dependency Injection framework" href="http://www.codeplex.com/unity" target="_blank"&gt;Unity&lt;/a&gt; Dependency Injection (DI) framework is used to pave the path for unit testing and dependency injection. It offers Inversion of Control (IoC), which enables testing individual classes in isolation. Moreover, it has a handy feature to control lifetime of objects. Instead of creating instance of commonly used classes several times within the same request, you can make instances thread level, which means only one instance is created per thread and subsequent calls reuse the same instance. Are these going over your head? No worries, continue reading, I will explain later on.&lt;/p&gt;  &lt;p&gt;Fifthly, enabling API for Silverlight widgets allows more interactive widgets to be built using Silverlight. HTML and Javascripts still have limitations on smooth graphics and continuous transmission of data from web server. Silverlight solves all of these problems.&lt;/p&gt;  &lt;p&gt;Read the article for details on how all these improvements were done and how all these hot techs play together in a very useful open source project for enterprises.&lt;/p&gt;  &lt;p&gt;&lt;a title="Web 2.0 AJAX Portal using jQuery, ASP.NET 3.5, Silverlight, Linq to SQL, WF and Unity" href="http://www.codeproject.com/KB/ajax/Web20Portal.aspx"&gt;http://www.codeproject.com/KB/ajax/Web20Portal.aspx&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Don’t forget to vote for me if you like it.&lt;/p&gt;&lt;div class="wlWriterHeaderFooter" style="text-align:left;margin:0px;padding:4px 4px 4px 4px;"&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http://msmvps.com/blogs/omar/archive/2009/04/08/web-2-0-ajax-portal-using-jquery-asp-net-3-5-silverlight-linq-to-sql-wf-and-unity.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http://msmvps.com/blogs/omar/archive/2009/04/08/web-2-0-ajax-portal-using-jquery-asp-net-3-5-silverlight-linq-to-sql-wf-and-unity.aspx&amp;amp;bgcolor=0080C0&amp;amp;fgcolor=FFFFFF&amp;amp;border=000000&amp;amp;cbgcolor=808080&amp;amp;cfgcolor=000000" alt="DotNetKicks Image" border="0/" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1685991" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/asp.net/default.aspx">asp.net</category><category domain="http://msmvps.com/blogs/omar/archive/tags/linq/default.aspx">linq</category><category domain="http://msmvps.com/blogs/omar/archive/tags/workflow/default.aspx">workflow</category><category domain="http://msmvps.com/blogs/omar/archive/tags/javascript/default.aspx">javascript</category><category domain="http://msmvps.com/blogs/omar/archive/tags/ajax/default.aspx">ajax</category><category domain="http://msmvps.com/blogs/omar/archive/tags/.net/default.aspx">.net</category><category domain="http://msmvps.com/blogs/omar/archive/tags/silverlight/default.aspx">silverlight</category></item><item><title>Memory Leak with delegates and workflow foundation</title><link>http://msmvps.com/blogs/omar/archive/2009/03/14/memory-leak-with-delegates-and-workflow-foundation.aspx</link><pubDate>Sat, 14 Mar 2009 08:35:53 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1678020</guid><dc:creator>omar</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/omar/rsscomments.aspx?PostID=1678020</wfw:commentRss><comments>http://msmvps.com/blogs/omar/archive/2009/03/14/memory-leak-with-delegates-and-workflow-foundation.aspx#comments</comments><description>&lt;p&gt;Recently after Load Testing my open source project &lt;a href="http://www.dropthings.com" target="_blank"&gt;Dropthings&lt;/a&gt;, I encountered a lot of memory leak. I found lots of Workflow Instances and Linq Entities were left in memory and never collected. After profiling the web application using &lt;a title="Memory Profiler for .NET" href="http://memprofiler.com/" target="_blank"&gt;.NET Memory Profiler&lt;/a&gt;, it showed the real picture:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_41151CF2.png"&gt;&lt;img title="image" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="646" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_416D161B.png" width="605" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;It shows you that instances of the several types are being created but not being removed. You see the “New” column has positive value, but the “Remove” column has 0. That means new instances are being created, but not removed. Basically the way you do Memory Profiling is, you take two snapshots. Say you take one snapshot when you first visit your website. Then you do some action on the website that results in allocation of objects. Then you take another snapshot. When you compare both snapshots, you can see how many instances of classes were created between these two snapshots and how many were removed. If they are not equal, then you have leak. Generally in web application many objects are created on every page hit and the end of the request, all those objects are supposed to be released. If they are not released, then we have a problem. But that’s the scenario for desktop applications because in a desktop application, objects can remain in memory until app is closed. But you should know best from the code which objects were supposed to go out of scope and get released.&lt;/p&gt;  &lt;p&gt;For beginners, leak means objects are being allocated but not being freed because someone is holding reference to the objects. When objects leak, they remain in memory forever, until the process (or app domain) is closed. So, if you have a leaky website, your website is continuously taking up memory until it runs out of memory on the web server and thus crash. So, memory leak is a bad – it prevents you from running your product for long duration and requires frequent restart of app pool. &lt;/p&gt;  &lt;p&gt;So, the above screenshot shows Workflow and Linq related classes are not being removed, and thus leaking. This means somewhere workflow instances are not being released and thus all workflow related objects are remaining. You can see the number is same 48 for all workflow related objects. This is a good indication that, almost every instance of workflow is leaked because there were total 48 workflows created and ran. Moreover it indicates we have a leak from a top Workflow instance level, not in some specific Activity or somewhere deep in the code.&lt;/p&gt;  &lt;p&gt;As the workflows use Linq stuff, they held reference to the Linq stuffs and thus the Linq stuffs leaked as well. Sometimes you might be looking for why A is leaking. But you actually end up finding that since B was holding reference to A and B was leaking and thus A was leaking as well. This is sometimes tricky to figure out and you spend a lot of time looking at the wrong direction.&lt;/p&gt;  &lt;p&gt;Now let me show you the buggy code:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;ManualWorkflowSchedulerService manualScheduler &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;br /&gt;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;  workflowRuntime&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;GetService&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;ManualWorkflowSchedulerService&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;gt;();

&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WorkflowInstance instance &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;workflowRuntime&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;CreateWorkflow&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;workflowType&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;properties&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;);
&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;instance&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Start&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;();

&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#2b91af;"&gt;EventHandler&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WorkflowCompletedEventArgs&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;gt; &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;completedHandler &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;null&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;
&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;completedHandler &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;delegate&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;object &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;o&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WorkflowCompletedEventArgs e&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;)
{
    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;if &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;e&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WorkflowInstance&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;InstanceId &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;== &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;instance&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;InstanceId&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;) &lt;span style="background:#3f3f3f;color:#7f9f7f;"&gt;// 1. instance&lt;/span&gt;
    {
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;workflowRuntime&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WorkflowCompleted &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;-= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;completedHandler&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;; &lt;span style="background:#3f3f3f;color:#7f9f7f;"&gt;// 2. terminatedhandler&lt;/span&gt;

        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#7f9f7f;"&gt;// copy the output parameters in the specified properties dictionary
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;Dictionary&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;string&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;,&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;object&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#2b91af;"&gt;Enumerator &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;enumerator &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;br /&gt;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;            e&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;OutputParameters&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;GetEnumerator&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;();
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;while&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;( &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;enumerator&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;MoveNext&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;() )
        {
            &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#2b91af;"&gt;KeyValuePair&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;string&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;,&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;object&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;gt; &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;pair &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;enumerator&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Current&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;
            &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;if&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;( &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;properties&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;ContainsKey&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;pair&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Key&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;) )
            {
                &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;properties&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;[&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;pair&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Key&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;] = &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;pair&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Value&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;
            }
        }
    }
};

&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;Exception &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;x  &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;null&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;
&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#2b91af;"&gt;EventHandler&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WorkflowTerminatedEventArgs&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;gt; &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;terminatedHandler &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;null&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;
&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;terminatedHandler &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;delegate&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;object &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;o&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WorkflowTerminatedEventArgs e&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;)
{
    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;if &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;e&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WorkflowInstance&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;InstanceId &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;== &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;instance&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;InstanceId&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;) &lt;span style="background:#3f3f3f;color:#7f9f7f;"&gt;// 3. instance&lt;/span&gt;
    {
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;workflowRuntime&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WorkflowTerminated &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;-= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;terminatedHandler&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;; &lt;span style="background:#3f3f3f;color:#7f9f7f;"&gt;// 4. completeHandler&lt;/span&gt;
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Debug&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WriteLine&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;( &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;e&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Exception &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;);

        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;x &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;e&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Exception&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;
    }
};

&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;workflowRuntime&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WorkflowCompleted &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;+= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;completedHandler&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;
&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;workflowRuntime&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WorkflowTerminated &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;+= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;terminatedHandler&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;

&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;manualScheduler&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;RunWorkflow&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;instance&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;InstanceId&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;);&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Can you spot the code where it leaked?&lt;/p&gt;

&lt;p&gt;I have numbered the lines in comment where the leak is happening. Here the &lt;code&gt;delegate&lt;/code&gt; is acting like a closure and those who are from Javascript background know closure is evil. They leak memory unless very carefully written. Here the &lt;code&gt;delegate&lt;/code&gt; keeps a reference to the &lt;code&gt;instance&lt;/code&gt; object. So, if somehow &lt;code&gt;delegate&lt;/code&gt; is not released, the &lt;code&gt;instance&lt;/code&gt; will remain in memory forever and thus leak. Now can you find a situation when the &lt;code&gt;delegate&lt;/code&gt; will not be released?&lt;/p&gt;

&lt;p&gt;Say the workflow completed. It will fire the &lt;font color="#990000"&gt;completeHandler&lt;code&gt;. &lt;/code&gt;&lt;/font&gt;But the &lt;code&gt;completeHandler&lt;/code&gt; will not release the &lt;code&gt;terminateHandler&lt;code&gt;. &lt;/code&gt;&lt;/code&gt;Thus the &lt;code&gt;terminateHandler&lt;/code&gt; remains in memory and it also holds reference to the &lt;code&gt;instance&lt;/code&gt;. So, we have a leaky &lt;code&gt;delegate&lt;/code&gt; leaking whatever it is holding onto outside it’s scope. Here the only thing outside the scope if the &lt;code&gt;instance&lt;/code&gt;, which it is tried to access from the parent function.&lt;/p&gt;

&lt;p&gt;Since the workflow instance is not released, all the properties the workflow and all the activities inside it are holding onto remains in memory. Most of the workflows and activities expose public properties which are Linq Entities. Thus the Linq Entities remain in memory. Now Linq Entities keep a reference to the &lt;code&gt;DataContext&lt;/code&gt; from where it is produced. Thus we have &lt;code&gt;DataContext&lt;/code&gt; remaining in memory. Moreover, &lt;code&gt;DataContext&lt;/code&gt; keeps reference to many internal objects and metadata cacahe, so they remain in memory as well.&lt;/p&gt;

&lt;p&gt;So, the correct code is:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;ManualWorkflowSchedulerService &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;manualScheduler &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;workflowRuntime&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;GetService&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;ManualWorkflowSchedulerService&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;gt;();

&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;WorkflowInstance &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;instance &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;workflowRuntime&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;CreateWorkflow&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;workflowType&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;properties&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;);
&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;instance&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Start&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;();
&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;var &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;instanceId &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;instance&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;InstanceId&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;

&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#2b91af;"&gt;EventHandler&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;WorkflowCompletedEventArgs&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;gt; &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;completedHandler &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;null&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;
&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;completedHandler &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;delegate&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;object &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;o&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;WorkflowCompletedEventArgs &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;e&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;)
{
    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;if &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;e&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WorkflowInstance&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;InstanceId &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;== &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;instanceId&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;) &lt;span style="background:#3f3f3f;color:#7f9f7f;"&gt;// 1. instanceId is a Guid&lt;/span&gt;
    {
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#7f9f7f;"&gt;// copy the output parameters in the specified properties dictionary
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;Dictionary&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;string&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;,&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;object&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#2b91af;"&gt;Enumerator &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;enumerator &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;br /&gt;                &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;e&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;OutputParameters&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;GetEnumerator&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;();
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;while&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;( &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;enumerator&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;MoveNext&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;() )
        {
            &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#2b91af;"&gt;KeyValuePair&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;string&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;,&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;object&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;gt; &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;pair &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;enumerator&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Current&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;
            &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;if&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;( &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;properties&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;ContainsKey&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;pair&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Key&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;) )
            {
                &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;properties&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;[&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;pair&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Key&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;] = &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;pair&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Value&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;
            }
        }
    }
};

&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;Exception &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;x  &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;null&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;
&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#2b91af;"&gt;EventHandler&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;WorkflowTerminatedEventArgs&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;gt; &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;terminatedHandler &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;null&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;
&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;terminatedHandler &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;delegate&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;object &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;o&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;WorkflowTerminatedEventArgs &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;e&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;)
{
    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;if &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;e&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WorkflowInstance&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;InstanceId &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;== &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;instanceId&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;) &lt;span style="background:#3f3f3f;color:#7f9f7f;"&gt;// 2. instanceId is a Guid&lt;/span&gt;
    {
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;x &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;e&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Exception&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;Debug&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WriteLine&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;e&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Exception&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;);
    }
};

&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;workflowRuntime&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WorkflowCompleted &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;+= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;completedHandler&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;
&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;workflowRuntime&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WorkflowTerminated &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;+= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;terminatedHandler&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;

&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;manualScheduler&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;RunWorkflow&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;instance&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;InstanceId&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;);
&lt;span style="background:#3f3f3f;color:#7f9f7f;"&gt;// 3. Both delegates are now released&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;workflowRuntime&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WorkflowTerminated &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;-= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;terminatedHandler&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;
&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;workflowRuntime&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WorkflowCompleted &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;-= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;completedHandler&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;There are two changes – in both delegates, the &lt;code&gt;instanceId&lt;/code&gt; variable is passed, instead of the instance. Since &lt;code&gt;instanceId&lt;/code&gt; is a &lt;code&gt;Guid&lt;/code&gt;, which is a struct type data type, not a class, there’s no issue of referencing. Structs are copied, not referenced. So, they don’t leak memory. Secondly, both &lt;code&gt;delegate&lt;/code&gt;s are released at the end of the workflow execution, thus releasing both references.&lt;/p&gt;

&lt;p&gt;In Dropthings, I am using the famous &lt;a title="CallWorkflow Activity" href="http://www.masteringbiztalk.com/blogs/jon/PermaLink,guid,7be9fb53-0ddf-4633-b358-01c3e9999088.aspx" target="_blank"&gt;CallWorkflow Activity by John Flanders&lt;/a&gt;, which is widely used to execute one Workflow from another synchronously. There’s a &lt;code&gt;CallWorkflowService&lt;/code&gt; class which is responsible for synchronously executing another workflow and that has similar memory leak problem. The original code of the service is as following:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;public class &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;CallWorkflowService &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;: &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WorkflowRuntimeService
&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;{
    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfaf8f;"&gt;#region &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;Methods

    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;public void &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;StartWorkflow&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;Type &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;workflowType&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;,&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;Dictionary&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;string&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;,&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;object&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;gt; &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;inparms&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;, &lt;br /&gt;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#2b91af;"&gt;           Guid &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;caller&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;,&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#2b91af;"&gt;IComparable &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;qn&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;)
    {
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WorkflowRuntime wr &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;this&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Runtime&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WorkflowInstance wi &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;wr&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;CreateWorkflow&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;workflowType&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;,&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;inparms&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;);
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;wi&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Start&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;();
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;ManualWorkflowSchedulerService ss &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;br /&gt;             &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;wr&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;GetService&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;ManualWorkflowSchedulerService&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;gt;();
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;if &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;ss &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;!= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;null&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;)
            &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;ss&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;RunWorkflow&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;wi&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;InstanceId&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;);
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#2b91af;"&gt;EventHandler&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WorkflowCompletedEventArgs&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;gt; &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;d  &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;null&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;d &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;delegate&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;object &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;o&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WorkflowCompletedEventArgs e&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;)
        {
            &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;if &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;e&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WorkflowInstance&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;InstanceId &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;==&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;wi&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;InstanceId&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;)
            {
                &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;wr&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WorkflowCompleted &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;-= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;d&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;
                &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WorkflowInstance c &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;wr&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;GetWorkflow&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;caller&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;);
                &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;c&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;EnqueueItem&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;qn&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;e&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;OutputParameters&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;null&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;null&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;);
            }
        };
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#2b91af;"&gt;EventHandler&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WorkflowTerminatedEventArgs&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;gt; &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;te &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;null&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;te &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;delegate&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;object &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;o&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WorkflowTerminatedEventArgs e&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;)
        {
            &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;if &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;e&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WorkflowInstance&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;InstanceId &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;== &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;wi&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;InstanceId&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;)
            {
                &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;wr&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WorkflowTerminated &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;-= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;te&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;
                &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WorkflowInstance c &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;wr&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;GetWorkflow&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;caller&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;);
                &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;c&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;EnqueueItem&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;qn&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;new &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;Exception&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#c89191;"&gt;&amp;quot;Called Workflow Terminated&amp;quot;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;, &lt;br /&gt;                  &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;e&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Exception&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;), &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;null&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;null&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;);
            }
        };
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;wr&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WorkflowCompleted &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;+= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;d&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;wr&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WorkflowTerminated &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;+= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;te&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;
    }

    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfaf8f;"&gt;#endregion &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;Methods
}&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;As you see, it has that same delegate holding reference to instance object problem. Moreover, there’s some queue stuff there, which requires the &lt;code&gt;caller&lt;/code&gt; and &lt;code&gt;qn&lt;/code&gt; parameter passed to the &lt;code&gt;StartWorkflow&lt;/code&gt; function. So, not a straight forward fix. &lt;/p&gt;

&lt;p&gt;I tried to rewrite the whole &lt;code&gt;CallWorkflowService&lt;/code&gt; so that it does not require two delegates to be created per Workflow. Then I took the delegates out. Thus there’s no chance of closure holding reference to unwanted objects. The result looks like this:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;public class &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;CallWorkflowService &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;: &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;WorkflowRuntimeService
&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;{
    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfaf8f;"&gt;#region &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;Fields

    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;private &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#2b91af;"&gt;EventHandler&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;WorkflowCompletedEventArgs&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;gt; &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;_CompletedHandler &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;null&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;
    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;private &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#2b91af;"&gt;EventHandler&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;WorkflowTerminatedEventArgs&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;gt; &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;_TerminatedHandler &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;null&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;
    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;private &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;Dictionary&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#2b91af;"&gt;Guid&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#2b91af;"&gt;WorkflowInfo&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;gt; &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;_WorkflowQueue &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;br /&gt;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;       new &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;Dictionary&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#2b91af;"&gt;Guid&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#2b91af;"&gt;WorkflowInfo&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;gt;();

    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfaf8f;"&gt;#endregion &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;Fields

    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfaf8f;"&gt;#region &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;Methods

    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;public void &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;StartWorkflow&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;Type &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;workflowType&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;,&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;Dictionary&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;string&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;,&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;object&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;gt; &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;inparms&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;,&lt;br /&gt;        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#2b91af;"&gt;Guid &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;caller&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;,&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#2b91af;"&gt;IComparable &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;qn&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;)
    {
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;WorkflowRuntime &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;wr &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;this&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Runtime&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;WorkflowInstance &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;wi &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;wr&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;CreateWorkflow&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;workflowType&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;,&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;inparms&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;);
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;wi&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Start&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;();

        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;var &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;instanceId &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;wi&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;InstanceId&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;_WorkflowQueue&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;[&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;instanceId&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;] = &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;new &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#2b91af;"&gt;WorkflowInfo &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;{ &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Caller &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;caller&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;qn &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;qn &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;};

        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;ManualWorkflowSchedulerService &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;ss &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;br /&gt;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;           wr&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;GetService&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;ManualWorkflowSchedulerService&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;gt;();
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;if &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;ss &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;!= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;null&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;)
            &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;ss&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;RunWorkflow&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;wi&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;InstanceId&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;);
    }

    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;protected override void &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;OnStarted&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;()
    {
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;base&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;OnStarted&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;();

        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;if &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;null &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;== &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;_CompletedHandler&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;)
        {
            &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;_CompletedHandler &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;delegate&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;object &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;o&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;WorkflowCompletedEventArgs &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;e&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;)
            {
                &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;var &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;instanceId &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;e&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WorkflowInstance&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;InstanceId&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;
                &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;if &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;_WorkflowQueue&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;ContainsKey&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;instanceId&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;))
                {
                    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#2b91af;"&gt;WorkflowInfo &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;wf &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;_WorkflowQueue&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;[&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;instanceId&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;];
                    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;WorkflowInstance &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;c &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;this&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Runtime&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;GetWorkflow&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;wf&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Caller&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;);
                    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;c&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;EnqueueItem&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;wf&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;qn&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;e&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;OutputParameters&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;null&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;null&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;);
                    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;_WorkflowQueue&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Remove&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;instanceId&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;);
                }
            };
            &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;this&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Runtime&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WorkflowCompleted &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;+= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;_CompletedHandler&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;
        }

        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;if &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;null &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;== &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;_TerminatedHandler&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;)
        {
            &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;_TerminatedHandler &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;delegate&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;object &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;o&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;WorkflowTerminatedEventArgs &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;e&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;)
            {
                &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;var &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;instanceId &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;e&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WorkflowInstance&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;InstanceId&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;
                &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;if &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;_WorkflowQueue&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;ContainsKey&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;instanceId&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;))
                {
                    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#2b91af;"&gt;WorkflowInfo &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;wf &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;_WorkflowQueue&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;[&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;instanceId&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;];
                    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;WorkflowInstance &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;c &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;this&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Runtime&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;GetWorkflow&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;wf&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Caller&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;);
                    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;c&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;EnqueueItem&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;wf&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;qn&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;, &lt;br /&gt;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;                      new &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;Exception&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#c89191;"&gt;&amp;quot;Called Workflow Terminated&amp;quot;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;e&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Exception&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;), &lt;br /&gt;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;                      null&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;null&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;);
                    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;_WorkflowQueue&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Remove&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;instanceId&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;);
                }
            };

            &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;this&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Runtime&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WorkflowTerminated &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;+= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;_TerminatedHandler&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;
        }
    }

    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;protected override void &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;OnStopped&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;()
    {
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;_WorkflowQueue&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Clear&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;();

        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;base&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;OnStopped&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;();
    }

    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfaf8f;"&gt;#endregion &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;Methods

    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfaf8f;"&gt;#region &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;Nested Types

    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;private struct &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#2b91af;"&gt;WorkflowInfo
    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;{
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfaf8f;"&gt;#region &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;Fields

        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;public &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#2b91af;"&gt;Guid &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Caller&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;public &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#2b91af;"&gt;IComparable &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;qn&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;

        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfaf8f;"&gt;#endregion &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;Fields
    }

    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfaf8f;"&gt;#endregion &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;Nested Types
}&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;After fixing the problem, another Memory Profile result showed the leak is gone:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_0CF441A2.png"&gt;&lt;img title="image" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="601" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_2BCA8B51.png" width="564" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;As you see, the numbers vary, which means there’s no consistent leak. Moreover, looking at the types that remains in memory, they look more like metadata than instances of classes.&amp;#160; So, they are basically cached instances of metadata, not instances allocated during workflow execution which are supposed to be freed. So, we solved the memory leak!&lt;/p&gt;

&lt;p&gt;Now you know how to write anonymous delegates without leaking memory and how to run workflow without leaking them. Basically, the principle theory is – if you are referencing some outside object from an anonymous &lt;code&gt;delegate&lt;/code&gt;, make sure that object is not holding reference to the &lt;code&gt;delegate&lt;/code&gt; in some way, may be directly or may be via some child objects of its own. Because then you have a circular reference. If possible, do not try to access objects e.g. &lt;code&gt;instance&lt;/code&gt; inside an anonymous delegate that is declared outside the delegate. Try accessing instrinsic data types like int, string, DateTime, Guid etc which are not reference type variables. So, instead of referencing to an object, you should declare local variables e.g. &lt;code&gt;instanceId&lt;/code&gt; that gets the value of properties (e.g. &lt;code&gt;instance.InstanceId&lt;/code&gt;) from the object and then use those local variables inside the anonymous delegate.&lt;/p&gt;&lt;div class="wlWriterHeaderFooter" style="text-align:left;margin:0px;padding:4px 4px 4px 4px;"&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http://msmvps.com/blogs/omar/archive/2009/03/14/memory-leak-with-delegates-and-workflow-foundation.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http://msmvps.com/blogs/omar/archive/2009/03/14/memory-leak-with-delegates-and-workflow-foundation.aspx&amp;amp;bgcolor=0080C0&amp;amp;fgcolor=FFFFFF&amp;amp;border=000000&amp;amp;cbgcolor=808080&amp;amp;cfgcolor=000000" alt="DotNetKicks Image" border="0/" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1678020" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/performance/default.aspx">performance</category><category domain="http://msmvps.com/blogs/omar/archive/tags/linq/default.aspx">linq</category><category domain="http://msmvps.com/blogs/omar/archive/tags/workflow/default.aspx">workflow</category><category domain="http://msmvps.com/blogs/omar/archive/tags/.net/default.aspx">.net</category></item><item><title>Optimize ASP.NET Membership Stored Procedures for greater speed and scalability</title><link>http://msmvps.com/blogs/omar/archive/2009/03/13/optimize-asp-net-membership-stored-procedures-for-greater-speed-and-scalability.aspx</link><pubDate>Fri, 13 Mar 2009 13:23:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1678004</guid><dc:creator>omar</dc:creator><slash:comments>8</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/omar/rsscomments.aspx?PostID=1678004</wfw:commentRss><comments>http://msmvps.com/blogs/omar/archive/2009/03/13/optimize-asp-net-membership-stored-procedures-for-greater-speed-and-scalability.aspx#comments</comments><description>&lt;p&gt;Last year at &lt;a href="http://www.pageflakes.com" title="Pageflakes - Web 2.0 AJAX portal" target="_blank"&gt;Pageflakes&lt;/a&gt;, when we were getting millions of hits per day, we were having query timeout due to lock timeout and Transaction Deadlock errors. These locks were produced from &lt;code&gt;aspnet_Users&lt;/code&gt; and &lt;code&gt;aspnet_Membership&lt;/code&gt; tables. Since both of these tables are very high read (almost every request causes a read on these tables) and high write (every anonymous visit creates a row on &lt;code&gt;aspnet_Users&lt;/code&gt;), there were just way too many locks created on these tables per second. SQL Counters showed thousands of locks per second being created. Moreover, we had queries that would select thousands of rows from these tables frequently and thus produced more locks for longer period, forcing other queries to timeout and thus throw errors on the website.&lt;/p&gt;
&lt;p&gt;If you have &lt;a href="http://msmvps.com/blogs/omar/archive/2009/03/07/linq-to-sql-solve-transaction-deadlock-and-query-timeout-problem-using-uncommitted-reads.aspx" title="Solve Transaction Deadlock and Lock Contention in Linq to Sql" target="_blank"&gt;read my last blog post&lt;/a&gt;, you know why such locks happen. Basically every table when it grows up to hold millions of records and becomes popular goes through this trouble. It&amp;rsquo;s just a part of scalability problem that is common to database. But we rarely take prevention about it in our early design.&lt;/p&gt;
&lt;p&gt;The solution is simple, you should either have &lt;code&gt;WITH (NOLOCK)&lt;/code&gt; or &lt;code&gt;SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED&lt;/code&gt; before SELECT queries. Either of this will do. They tell SQL Server not to hold any lock on the table while it is reading the table. If some row is locked while the read is happening, it will just ignore that row. When you are reading a table thousand times per second, without these options, you are issuing lock on many places around the table thousand times per second. It not only makes read from table slower, but also so many lock prevents insert, update, delete from happening timely and thus queries timeout. If you have queries like &amp;ldquo;show the currently online users from last one hour based on &lt;code&gt;LastActivityDate&lt;/code&gt; field&amp;rdquo;, that is going to issue such a wide lock that even other harmless select queries will timeout. And did I tell you that there&amp;rsquo;s no index on &lt;code&gt;LastActivityDate&lt;/code&gt; on &lt;code&gt;aspnet_Users&lt;/code&gt; table?&lt;/p&gt;
&lt;p&gt;Now don&amp;rsquo;t blame yourself for not putting either of these options on your every stored proc and every dynamically generated SQL from the very first day. ASP.NET developers made the same mistake. You won&amp;rsquo;t see either of these used in any of the stored procs used by ASP.NET Membership. For example, the following stored proc gets called whenever you access &lt;code&gt;Profile&lt;/code&gt; object:&lt;/p&gt;
&lt;pre class="code"&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;ALTER PROCEDURE &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;[dbo]&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;[aspnet_Profile_GetProperties]&lt;br /&gt;    @ApplicationName      &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;nvarchar&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#8acccf;"&gt;256&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;),&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@UserName             &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;nvarchar&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#8acccf;"&gt;256&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;),&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@CurrentTimeUtc       &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;datetime&lt;br /&gt;AS&lt;br /&gt;BEGIN&lt;br /&gt;&lt;br /&gt;    DECLARE &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@ApplicationId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;uniqueidentifier&lt;br /&gt;    SELECT  &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@ApplicationId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;NULL&lt;br /&gt;    SELECT  &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@ApplicationId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;ApplicationId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;FROM &lt;br /&gt;&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;      dbo&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;aspnet_Applications &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;WHERE LOWER&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@ApplicationName&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;) = &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;LoweredApplicationName&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;IF &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@ApplicationId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;IS NULL&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;)&lt;br /&gt;        &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;RETURN&lt;br /&gt;&lt;br /&gt;    DECLARE &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@UserId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;uniqueidentifier&lt;br /&gt;    DECLARE &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@LastActivityDate &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;datetime&lt;br /&gt;    SELECT  &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@UserId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;NULL&lt;br /&gt;&lt;br /&gt;    SELECT &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@UserId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;UserId&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@LastActivityDate &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;LastActivityDate&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;FROM   &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;dbo&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;aspnet_Users &lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;WHERE  &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;ApplicationId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@ApplicationId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;AND &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;LoweredUserName &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;LOWER&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@UserName&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;)&lt;br /&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;IF &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@UserId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;IS NULL&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;)&lt;br /&gt;        &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;RETURN&lt;br /&gt;    SELECT TOP &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#8acccf;"&gt;1 &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;PropertyNames&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;PropertyValuesString&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;PropertyValuesBinary&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;FROM         &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;dbo&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;aspnet_Profile&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;WHERE        &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;UserId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@UserId&lt;br /&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;IF &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@@ROWCOUNT &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;&amp;gt; &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#8acccf;"&gt;0&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;)&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;BEGIN&lt;br /&gt;        UPDATE &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;dbo&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;aspnet_Users&lt;br /&gt;        &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;SET    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;LastActivityDate&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;=&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@CurrentTimeUtc&lt;br /&gt;        &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;WHERE  &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;UserId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@UserId&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;END&lt;br /&gt;END&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;There are two SELECT operations that hold lock on two very high read tables &amp;ndash; &lt;code&gt;aspnet_Users&lt;/code&gt; and &lt;code&gt;aspnet_Profile&lt;/code&gt;. Moreover, there&amp;rsquo;s a nasty UPDATE statement. It tries to update the &lt;code&gt;LastActivityDate&lt;/code&gt; of a user whenever you access &lt;code&gt;Profile&lt;/code&gt; object for the first time within a http request. &lt;/p&gt;
&lt;p&gt;This stored proc alone is enough to bring your site down. It did to us because we are using &lt;code&gt;Profile&lt;/code&gt; Provider everywhere. This stored proc was called around 300 times/sec. We were having nightmarish slow performance on the website and many lock timeouts and transaction deadlocks. So, we added the transaction isolation level and we also modified the UPDATE statement to only perform an update when the &lt;code&gt;LastActivityDate&lt;/code&gt; is over an hour. So, this means, the same user&amp;rsquo;s &lt;code&gt;LastActivityDate&lt;/code&gt; won&amp;rsquo;t be updated if the user hits the site within the same hour.&lt;/p&gt;
&lt;p&gt;So, after the modifications, the stored proc looked like this:&lt;/p&gt;
&lt;pre class="code"&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;ALTER PROCEDURE &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;[dbo]&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;[aspnet_Profile_GetProperties]&lt;br /&gt;    @ApplicationName      &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;nvarchar&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#8acccf;"&gt;256&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;),&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@UserName             &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;nvarchar&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#8acccf;"&gt;256&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;),&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@CurrentTimeUtc       &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;datetime&lt;br /&gt;AS&lt;br /&gt;BEGIN&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#7f9f7f;"&gt;-- 1. Please no more locks during reads&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;;&lt;br /&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;DECLARE &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@ApplicationId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;uniqueidentifier&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#7f9f7f;"&gt;--SELECT  @ApplicationId = NULL&lt;br /&gt;    --SELECT  @ApplicationId = ApplicationId FROM dbo.aspnet_Applications &lt;br /&gt;    WHERE LOWER(@ApplicationName) = LoweredApplicationName&lt;br /&gt;    --IF (@ApplicationId IS NULL)&lt;br /&gt;    --    RETURN&lt;br /&gt;    &lt;br /&gt;    -- 2. No more call to Application table. We have only one app dude!&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;SET &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@ApplicationId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;dbo&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;udfGetAppId&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;()&lt;br /&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;DECLARE &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@UserId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;uniqueidentifier&lt;br /&gt;    DECLARE &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@LastActivityDate &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;datetime&lt;br /&gt;    SELECT  &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@UserId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;NULL&lt;br /&gt;&lt;br /&gt;    SELECT &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@UserId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;UserId&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@LastActivityDate &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;LastActivityDate&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;FROM   &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;dbo&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;aspnet_Users &lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;WHERE  &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;ApplicationId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@ApplicationId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;AND &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;LoweredUserName &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;LOWER&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@UserName&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;)&lt;br /&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;IF &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@UserId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;IS NULL&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;)&lt;br /&gt;        &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;RETURN&lt;br /&gt;    SELECT TOP &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#8acccf;"&gt;1 &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;PropertyNames&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;PropertyValuesString&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;PropertyValuesBinary&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;FROM         &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;dbo&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;aspnet_Profile&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;WHERE        &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;UserId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@UserId&lt;br /&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;IF &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@@ROWCOUNT &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;&amp;gt; &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#8acccf;"&gt;0&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;)&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;BEGIN&lt;br /&gt;        &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#7f9f7f;"&gt;-- 3. Do not update the same user within an hour&lt;br /&gt;        &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;IF DateDiff&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;n&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@LastActivityDate&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@CurrentTimeUtc&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;) &amp;gt; &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#8acccf;"&gt;60&lt;br /&gt;        &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;BEGIN&lt;br /&gt;            &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#7f9f7f;"&gt;-- 4. Use ROWLOCK to lock only a row since we know this query&lt;br /&gt;            -- is highly selective&lt;br /&gt;            &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;UPDATE &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;dbo&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;aspnet_Users &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;WITH&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;ROWLOCK&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;)&lt;br /&gt;            &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;SET    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;LastActivityDate&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;=&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@CurrentTimeUtc&lt;br /&gt;            &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;WHERE  &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;UserId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@UserId&lt;br /&gt;        &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;END&lt;br /&gt;    END&lt;br /&gt;END&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;The changes I made are numbered and commented. No need for further explanation. The only tricky thing here is, I have eliminate call to Application table just to get the ApplicationID from ApplicationName. Since there&amp;rsquo;s only one application in a database (ever heard of multiple applications storing their user separately on the same database and the same table?), we don&amp;rsquo;t need to look up the ApplicationID on every call to every Membership stored proc. We can just get the ID and hard code it in a function.&lt;/p&gt;
&lt;pre class="code"&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;CREATE FUNCTION &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;dbo&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;udfGetAppId&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;()&lt;br /&gt;&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;RETURNS uniqueidentifier&lt;br /&gt;WITH EXECUTE AS &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;CALLER&lt;br /&gt;&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;AS&lt;br /&gt;BEGIN&lt;br /&gt;    RETURN CONVERT&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;uniqueidentifier&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#c89191;"&gt;&amp;#39;fd639154-299a-4a9d-b273-69dc28eb6388&amp;#39;&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;)&lt;br /&gt;&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;END&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;This UDF returns the &lt;code&gt;ApplicationID&lt;/code&gt; that I have hardcoded copying from the Application table. Thus it eliminates the need for quering on the Application table. &lt;/p&gt;
&lt;p&gt;Similarly you should do the changes in all other stored procedures that belong to Membership Provider. All the stroc procs are missing proper locking, issues aggressive lock during update and too frequent updates than practical need. Most of them also try to resolve ApplicationID from ApplicationName, which is unnecessary when you have only one web application per database. Make these changes and enjoy lock contention free super performance from Membership Provider!&lt;/p&gt;
&lt;div class="wlWriterHeaderFooter" style="margin:0px;padding:4px;text-align:left;"&gt;
&lt;script type="text/javascript"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;&lt;/script&gt;
&lt;script src="http://widgets.dzone.com/widgets/zoneit.js" language="javascript"&gt;&lt;/script&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fmsmvps.com%2fblogs%2fomar%2farchive%2f2009%2f03%2f14%2foptimize-asp-net-membership-stored-procedures-for-greater-speed-and-scalability.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fmsmvps.com%2fblogs%2fomar%2farchive%2f2009%2f03%2f14%2foptimize-asp-net-membership-stored-procedures-for-greater-speed-and-scalability.aspx" alt="kick it on DotNetKicks.com" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1678004" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/sql+server/default.aspx">sql server</category><category domain="http://msmvps.com/blogs/omar/archive/tags/performance/default.aspx">performance</category><category domain="http://msmvps.com/blogs/omar/archive/tags/asp.net/default.aspx">asp.net</category><category domain="http://msmvps.com/blogs/omar/archive/tags/.net/default.aspx">.net</category></item><item><title>Linq to SQL solve Transaction deadlock and Query timeout problem using uncommitted reads</title><link>http://msmvps.com/blogs/omar/archive/2009/03/07/linq-to-sql-solve-transaction-deadlock-and-query-timeout-problem-using-uncommitted-reads.aspx</link><pubDate>Sat, 07 Mar 2009 07:30:52 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1676241</guid><dc:creator>omar</dc:creator><slash:comments>11</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/omar/rsscomments.aspx?PostID=1676241</wfw:commentRss><comments>http://msmvps.com/blogs/omar/archive/2009/03/07/linq-to-sql-solve-transaction-deadlock-and-query-timeout-problem-using-uncommitted-reads.aspx#comments</comments><description>&lt;p&gt;When your database tables start accumulating thousands of rows and many users start working on the same table concurrently, SELECT queries on the tables start producing lock contentions and transaction deadlocks. This is a common problem in any high volume website. As soon as you start getting several concurrent users hitting your website that results in SELECT queries on some large table like &lt;u&gt;aspnet_users&lt;/u&gt; table that are also being updated very frequently, you end up having one of these errors:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Transaction (Process ID ##) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction. &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Or,&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Timeout Expired. The Timeout Period Elapsed Prior To Completion Of The Operation Or The Server Is Not Responding. &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The solution to these problems are – use proper index on the table and use transaction isolation level &lt;u&gt;Read Uncommitted&lt;/u&gt; or &lt;u&gt;WITH (NOLOCK)&lt;/u&gt; in your SELECT queries. So, if you had a query like this:&lt;/p&gt;  &lt;pre class="csharpcode"&gt;SELECT * FORM aspnet_users &lt;br /&gt;&lt;span class="kwrd"&gt;where&lt;/span&gt; ApplicationID =’xxx’ AND LoweredUserName = &lt;span class="str"&gt;&amp;#39;someuser&amp;#39;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;You should end up having any of the above errors under high load. There are two ways to solve this:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;SET TRANSACTION LEVEL READ UNCOMMITTED;
SELECT * FROM aspnet_Users &lt;br /&gt;WHERE ApplicationID =’xxx’ AND LoweredUserName = &lt;span class="str"&gt;&amp;#39;someuser&amp;#39;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Or use the WITH (NOLOCK):&lt;/p&gt;

&lt;pre class="csharpcode"&gt;SELECT * FROM aspnet_Users WITH (NOLOCK) &lt;br /&gt;WHERE ApplicationID =’xxx’ AND LoweredUserName = &lt;span class="str"&gt;&amp;#39;someuser&amp;#39;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;The reason for the errors are that since &lt;u&gt;aspnet_users&lt;/u&gt; is a high read and high write table, during read, the table is partially locked and during write, it is also locked. So, when the locks overlap on each other from several queries and especially when there’s a query that’s trying to read a large number of rows and thus locking large number of rows, some of the queries either timeout or produce deadlocks.&lt;/p&gt;

&lt;p&gt;Linq to Sql does not produce queries with the &lt;u&gt;WITH (NOLOCK)&lt;/u&gt; option nor does it use &lt;u&gt;READ UNCOMMITTED&lt;/u&gt;. So, if you are using Linq to SQL queries, you are going to end up with any of these problems on production pretty soon when your site becomes highly popular.&lt;/p&gt;

&lt;p&gt;For example, here’s a very simple query:&lt;/p&gt;

&lt;pre class="code" style="background:#3f3f3f;"&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;using (&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;var &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;db &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;new &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;DropthingsDataContext&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;())
{
    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;var &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;user &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;db&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;aspnet_Users&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;First&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;();
    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;var &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;pages &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;user&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Pages&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;ToList&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;();
}&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&lt;u&gt;DropthingsDataContext&lt;/u&gt; is a &lt;u&gt;DataContext&lt;/u&gt; built from &lt;a title="Dropthings - Open Source AJAX Portal" href="http://www.dropthings.com/" target="_blank"&gt;Dropthings&lt;/a&gt; database.&lt;/p&gt;

&lt;p&gt;When you attach SQL Profiler, you get this:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_2B685BF8.png"&gt;&lt;img title="image" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="174" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_7A197197.png" width="639" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;You see none of the queries have READ UNCOMMITTED or WITH (NOLOCK). &lt;/p&gt;

&lt;p&gt;The fix is to do this:&lt;/p&gt;

&lt;pre class="code" style="background:#3f3f3f;"&gt;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;using (&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;var &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;db &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;new &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;DropthingsDataContext2&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;())
{
    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;db&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Connection&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Open&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;();
    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;db&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;ExecuteCommand&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#c89191;"&gt;&amp;quot;SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;&amp;quot;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;);

    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;var &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;user &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;db&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;aspnet_Users&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;First&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;();
    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;var &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;pages &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;user&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Pages&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;ToList&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;();
}&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;This will result in the following profiler output&lt;/p&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_5DBC09AA.png"&gt;&lt;img title="image" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="91" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_09202AA5.png" width="630" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;As you see, both queries execute within the same connection and the isolation level is set before the queries execute. So, both queries enjoy the isolation level.&lt;/p&gt;

&lt;p&gt;Now there’s a catch, the connection does not close. This seems to be a bug in the DataContext that when it is disposed, it does not dispose the connection it is holding onto. &lt;/p&gt;

&lt;p&gt;In order to solve this, I have made a child class of the &lt;u&gt;DropthingsDataContext&lt;/u&gt; named &lt;u&gt;DropthingsDataContext2&lt;/u&gt; which overrides the &lt;u&gt;Dispose&lt;/u&gt; method and closes the connection.&lt;/p&gt;

&lt;pre class="code" style="background:#3f3f3f;"&gt;   &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;class &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;DropthingsDataContext2 &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;: &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;DropthingsDataContext&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#2b91af;"&gt;IDisposable
    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;{
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;public new void &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Dispose&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;()
        {
            &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;if &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;base&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Connection &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;!= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;null&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;)
                &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;if &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;base&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Connection&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;State &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;!= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;System&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Data&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#2b91af;"&gt;ConnectionState&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Closed&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;)
                {
                    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;base&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Connection&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Close&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;();
                    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;base&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Connection&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Dispose&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;();
                }

            &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;base&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Dispose&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;();            
        }
    }&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;This solved the connection problem.&lt;/p&gt;

&lt;p&gt;There you have it, no more transaction deadlock or lock contention from Linq to SQL queries. But remember, this is only to eliminate such problems when your database already has the right indexes. If you do not have the proper index, then you will end up having lock contention and query timeouts anyway.&lt;/p&gt;

&lt;p&gt;There’s one more catch, READ UNCOMMITTED will return rows from transactions that have not completed yet. So, you might be reading rows from transactions that will rollback. Since that’s generally an exceptional scenario, you are more or less safe with uncommitted read, but not for financial applications where transaction rollback is a common scenario. In such case, go for committed read or repeatable read.&lt;/p&gt;

&lt;p&gt;There’s another way you can achieve the same, which seems to work, that is using .NET Transactions. Here’s the code snippet:&lt;/p&gt;

&lt;pre class="code" style="background:#3f3f3f;"&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;using &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;var &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;transaction &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;new &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;TransactionScope&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(
    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#2b91af;"&gt;TransactionScopeOption&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;RequiresNew&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;,
    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;new &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#2b91af;"&gt;TransactionOptions&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;()
    {
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;IsolationLevel &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#2b91af;"&gt;IsolationLevel&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;ReadUncommitted&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;,
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Timeout &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#2b91af;"&gt;TimeSpan&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;FromSeconds&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#8acccf;"&gt;30&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;)
    }))
{
    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;using &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;var &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;db &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;new &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#f0dfaf;"&gt;DropthingsDataContext&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;())
    {
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;var &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;user &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;db&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;aspnet_Users&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;First&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;();
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;var &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;pages &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;user&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Pages&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;ToList&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;();

        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;transaction&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Complete&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;();
    }
}&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Profiler shows a transaction begins and ends:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_48683F55.png"&gt;&lt;img title="image" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="273" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_0F118CC6.png" width="499" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The downside is it wraps your calls in a transaction. So, you are unnecessarily creating transactions even for SELECT operations. When you do this hundred times per second on a web application, it’s a significant over head. &lt;/p&gt;

&lt;p&gt;Some really good examples of deadlocks are given in this article:&lt;/p&gt;

&lt;p&gt;&lt;a title="http://www.code-magazine.com/article.aspx?quickid=0309101&amp;amp;page=2" href="http://www.code-magazine.com/article.aspx?quickid=0309101&amp;amp;page=2"&gt;http://www.code-magazine.com/article.aspx?quickid=0309101&amp;amp;page=2&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I highly recommend it.&lt;/p&gt;
&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fmsmvps.com%2fblogs%2fomar%2farchive%2f2009%2f03%2f07%2flinq-to-sql-solve-transaction-deadlock-and-query-timeout-problem-using-uncommitted-reads.aspx"&gt;&lt;img alt="kick it on DotNetKicks.com" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fmsmvps.com%2fblogs%2fomar%2farchive%2f2009%2f03%2f07%2flinq-to-sql-solve-transaction-deadlock-and-query-timeout-problem-using-uncommitted-reads.aspx" border="0" /&gt;&lt;/a&gt;&lt;div class="wlWriterHeaderFooter" style="text-align:left;margin:0px;padding:4px 4px 4px 4px;"&gt;&lt;script type="text/javascript"&gt;var dzone_url = &amp;#39;http://msmvps.com/blogs/omar/archive/2009/03/07/linq-to-sql-solve-transaction-deadlock-and-query-timeout-problem-using-uncommitted-reads.aspx&amp;#39;;&lt;/script&gt;&lt;script type="text/javascript"&gt;var dzone_title = &amp;#39;Linq to SQL solve Transaction deadlock and Query timeout problem using uncommitted reads&amp;#39;;&lt;/script&gt;&lt;script type="text/javascript"&gt;var dzone_blurb = &amp;#39;Linq to SQL solve Transaction deadlock and Query timeout problem using uncommitted reads&amp;#39;;&lt;/script&gt;&lt;script type="text/javascript"&gt;var dzone_style = &amp;#39;2&amp;#39;;&lt;/script&gt;&lt;script language="javascript" src="http://widgets.dzone.com/widgets/zoneit.js"&gt;&lt;/script&gt; &lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1676241" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/sql+server/default.aspx">sql server</category><category domain="http://msmvps.com/blogs/omar/archive/tags/performance/default.aspx">performance</category><category domain="http://msmvps.com/blogs/omar/archive/tags/linq/default.aspx">linq</category><category domain="http://msmvps.com/blogs/omar/archive/tags/.net/default.aspx">.net</category></item><item><title>Strongly typed workflow input and output arguments</title><link>http://msmvps.com/blogs/omar/archive/2008/12/27/strongly-typed-workflow-input-and-output-arguments.aspx</link><pubDate>Sat, 27 Dec 2008 15:05:45 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1657833</guid><dc:creator>omar</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/omar/rsscomments.aspx?PostID=1657833</wfw:commentRss><comments>http://msmvps.com/blogs/omar/archive/2008/12/27/strongly-typed-workflow-input-and-output-arguments.aspx#comments</comments><description>&lt;p&gt;When you run a &lt;u&gt;Workflow&lt;/u&gt; using Workflow Foundation, you pass arguments to the workflow in a &lt;u&gt;Dictionary&lt;/u&gt; form where the type of Dictionary is &lt;u&gt;Dictionary&amp;lt;string, object&amp;gt;&lt;/u&gt;. This means you miss the strong typing features of .NET languages. You have to know what arguments the workflow expects by looking at the &lt;u&gt;Workflow&lt;/u&gt; public properties. Moreover, there’s no way to make arguments required. You pass parameter, expect it to run, if it throws exception, you pass more arguments, hope it works now. Similarly, if you are running workflow synchronously using &lt;u&gt;ManualWorkflowSchedulerService&lt;/u&gt;, you expect return arguments from the Workflow immediately, but there again, you have to rely on the &lt;u&gt;Dictionary&lt;/u&gt; key and value pair. No strong typing there as well.&lt;/p&gt;  &lt;p&gt;In order to solve this, so that you could pass Workflow arguments as strongly typed classes, you can establish a format that every &lt;u&gt;Workflow&lt;/u&gt; has only two arguments named &amp;quot;Request” and “Response” and none other. Whatever needs to be passed to the &lt;u&gt;Workflow&lt;/u&gt; and expected out of it, must be passed via Request and must be expected via Response properties. Now the type of these arguments can be workflow specific, it can be any class with one or more parameters. This way, you could write code like this:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_0C53CAC7.png"&gt;&lt;img title="Running workflow with strongly typed argument" style="border-right:0px;border-top:0px;display:inline;border-left:0px;border-bottom:0px;" height="100" alt="Running workflow with strongly typed argument" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_0166C3B2.png" width="657" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The advantages of these strongly typed approach are: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Compile time validation of input parameters passed to workflow. No risk of passing unexpected object in Dictionary’s &lt;u&gt;object&lt;/u&gt; type value.&lt;/li&gt;    &lt;li&gt;Enforce required values by creating Request objects with non-default constructor.&lt;/li&gt;    &lt;li&gt;Establish a fixed contract for Workflow input and output via the strongly typed Request and Response classes or interfaces.&lt;/li&gt;    &lt;li&gt;Validate input arguments for the Workflow directly from the Request class, without going through the overhead of running a workflow.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;If we follow this approach, we create workflows with only two &lt;u&gt;DependencyProperty&lt;/u&gt;, one for &lt;u&gt;Request&lt;/u&gt; and one for &lt;u&gt;Response&lt;/u&gt;. Showing you an example from my open source project &lt;a title="Dropthings - Open Source AJAX Start Page" href="http://www.codeplex.com/dropthings" target="_blank"&gt;Dropthings&lt;/a&gt;, which uses Workflow for the entire Business Layer. Below you see the Workflow that executes when a new user visits &lt;a title="Dropthings - an Open Source AJAX Start Page" href="http://www.dropthings.com" target="_blank"&gt;Dropthings.com&lt;/a&gt;, creates a new user and setups all the pages and widgets for the user. It has only two &lt;u&gt;Dependency&lt;/u&gt; property – Request and Response.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_4C29C31A.png"&gt;&lt;img title="image" style="display:inline;" height="547" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_1A4E5A2B.png" width="595" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The Request parameters is of type &lt;u&gt;IUserVisitWorkflowRequest&lt;/u&gt;. So, you can pass any class as Request argument that implements the interface. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_65BD6215.png"&gt;&lt;img title="image" style="display:inline;" height="69" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_152BD0E2.png" width="637" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Here I have used fancy inheritance to create Request object hierarchy. You don’t need to do that. Just remember, you can pass any class. You don’t even need to use interface for Request parameter. It can be a class directly. I use all these interfaces in order to facilitate Dependency Inversion.&lt;/p&gt;  &lt;p&gt;Similarly, the Response object is also a class.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_366B2AE4.png"&gt;&lt;img title="image" style="display:inline;" height="117" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_23F2B462.png" width="656" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The Response returns quite some properties. So, it’s kinda handy to wrap them all in one property.&lt;/p&gt;  &lt;p&gt;So, there you have it, strongly typed Workflow arguments. You can attach properties of the Request object to any activity directly form the designer:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_6B37E487.png"&gt;&lt;img title="image" style="display:inline;" height="520" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_2B2E2875.png" width="534" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;There’s really no compromise to make in this approach. Everything works as before.&lt;/p&gt;  &lt;p&gt;In order to make workflow execution simpler, I use a helper method like the following, that takes the Request and Response object and creates the Dictionary for me. This Dictionary always contains one “Request” and one “Response” entry.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_066CEB31.png"&gt;&lt;img title="image" style="display:inline;" height="196" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_6A7BB638.png" width="498" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;This way, I can run Workflow in strongly typed fashion:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_6DA8C87A.png"&gt;&lt;img title="image" style="display:inline;" height="144" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_3DFA8421.png" width="646" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;Here I can specify the Request, Response and Workflow type using strong typing. This way I get strongly typed return object as well as pass strongly type Request object. There’s no dictionary building, no risky string key and object type value passing.&amp;#160; You can ignore the &lt;u&gt;ObjectContainer.Resolve()&lt;/u&gt; stuff, because that’s just returning me an existing reference of &lt;u&gt;WorkflowRuntime&lt;/u&gt;.&lt;/p&gt;  &lt;p&gt;Hope you like this approach.&lt;/p&gt;&lt;div class="wlWriterHeaderFooter" style="text-align:left;margin:0px;padding:4px 4px 4px 4px;"&gt;&lt;script type="text/javascript"&gt;var dzone_url = &amp;#39;http://msmvps.com/blogs/omar/archive/2008/12/27/strongly-typed-workflow-input-and-output-arguments.aspx&amp;#39;;&lt;/script&gt;&lt;script type="text/javascript"&gt;var dzone_title = &amp;#39;Strongly typed workflow input and output arguments&amp;#39;;&lt;/script&gt;&lt;script type="text/javascript"&gt;var dzone_blurb = &amp;#39;Strongly typed workflow input and output arguments&amp;#39;;&lt;/script&gt;&lt;script type="text/javascript"&gt;var dzone_style = &amp;#39;2&amp;#39;;&lt;/script&gt;&lt;script language="javascript" src="http://widgets.dzone.com/widgets/zoneit.js"&gt;&lt;/script&gt; &lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1657833" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/workflow/default.aspx">workflow</category><category domain="http://msmvps.com/blogs/omar/archive/tags/.net/default.aspx">.net</category><category domain="http://msmvps.com/blogs/omar/archive/tags/architecture/default.aspx">architecture</category></item><item><title>Linq to SQL: Delete an entity using Primary Key only</title><link>http://msmvps.com/blogs/omar/archive/2008/10/30/linq-to-sql-delete-an-entity-using-primary-key-only.aspx</link><pubDate>Thu, 30 Oct 2008 00:27:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1652462</guid><dc:creator>omar</dc:creator><slash:comments>18</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/omar/rsscomments.aspx?PostID=1652462</wfw:commentRss><comments>http://msmvps.com/blogs/omar/archive/2008/10/30/linq-to-sql-delete-an-entity-using-primary-key-only.aspx#comments</comments><description>&lt;p&gt;Linq to Sql does not come with a function like &lt;span style="text-decoration:underline;"&gt;.Delete(ID)&lt;/span&gt; which allows you to delete an entity using it&amp;rsquo;s primary key. You have to first get the object that you want to delete and then call &lt;span style="text-decoration:underline;"&gt;.DeleteOnSubmit(obj)&lt;/span&gt; to queue it for delete. Then you have to call &lt;span style="text-decoration:underline;"&gt;DataContext.SubmitChanges()&lt;/span&gt; to play the delete queries on database. So, how to delete object without getting them from database and avoid database roundtrip?&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_600F7C48.png"&gt;&lt;img title="Delete an object without getting it - Linq to Sql" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" alt="Delete an object without getting it - Linq to Sql" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_7AABF294.png" border="0" height="168" width="486" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;You can call this function using &lt;span style="text-decoration:underline;"&gt;DeleteByPK&amp;lt;Employee, int&amp;gt;(10, dataContext);&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;First type is the entity type and second one is the type of the primary key. If your object&amp;rsquo;s primary key is a &lt;span style="text-decoration:underline;"&gt;Guid&lt;/span&gt; field, specify &lt;span style="text-decoration:underline;"&gt;Guid&lt;/span&gt; instead of &lt;span style="text-decoration:underline;"&gt;int&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;How it works:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It figures out the table name and the primary key field name from the entity &lt;/li&gt;
&lt;li&gt;Then it uses the table name and primary key field name to build a DELETE query &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Figuring out the table name and primary key field name is a bit hard. There&amp;rsquo;s some reflection involved. The &lt;span style="text-decoration:underline;"&gt;GetTableDef&amp;lt;TSource&amp;gt;()&lt;/span&gt; returns the table name and primary key field name for an entity.&lt;/p&gt;
&lt;p&gt;Every Linq Entity class is decorated with a &lt;span style="text-decoration:underline;"&gt;Table&lt;/span&gt; attribute that has the table name:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_3E337DEA.png"&gt;&lt;img title="Lint entity declaration" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" alt="Lint entity declaration" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_3AD1E642.png" border="0" height="67" width="551" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Then the primary key field is decorated with a &lt;span style="text-decoration:underline;"&gt;Column&lt;/span&gt; attribute with &lt;span style="text-decoration:underline;"&gt;IsPrimaryKey = true&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_7C1CE8DB.png"&gt;&lt;img title="Primary Key field has Column attribute with IsPrimaryKey = true" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" alt="Primary Key field has Column attribute with IsPrimaryKey = true" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_031BD9BA.png" border="0" height="77" width="709" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;So, using reflection we can figure out the table name and the primary key property and the field name.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the code that does it:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_600B6849.png"&gt;&lt;img title="Using reflection find the Table attribute and the Column attribute" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" alt="Using reflection find the Table attribute and the Column attribute" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_722FCF72.png" border="0" height="615" width="685" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Before you scream &amp;ldquo;Reflection is SLOW!!!!&amp;rdquo; the definition is cached. So, reflection is used only once per appDomain per entity. Subsequent call is just a dictionary lookup away, which is as fast as it can get.&lt;/p&gt;
&lt;p&gt;You can also delete a collection of object without ever getting any one of them. The the following function to delete a whole bunch of objects:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_57CF1AB4.png"&gt;&lt;img title="Delete a list of objects using Linq to SQL" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" alt="Delete a list of objects using Linq to SQL" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_3925043E.png" border="0" height="398" width="553" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;The code is available here:&lt;/p&gt;
&lt;p&gt;&lt;a title="http://code.msdn.microsoft.com/DeleteEntitiesLinq" href="http://code.msdn.microsoft.com/DeleteEntitiesLinq"&gt;http://code.msdn.microsoft.com/DeleteEntitiesLinq&lt;/a&gt;&lt;/p&gt;
&lt;div class="wlWriterHeaderFooter" style="text-align:left;margin:0px;padding:4px 4px 4px 4px;"&gt;
&lt;script type="text/javascript"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;&lt;/script&gt;
&lt;script language="javascript" src="http://widgets.dzone.com/widgets/zoneit.js"&gt;&lt;/script&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fmsmvps.com%2fblogs%2fomar%2farchive%2f2008%2f10%2f30%2flinq-to-sql-delete-an-entity-using-primary-key-only.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fmsmvps.com%2fblogs%2fomar%2farchive%2f2008%2f10%2f30%2flinq-to-sql-delete-an-entity-using-primary-key-only.aspx" alt="kick it on DotNetKicks.com" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1652462" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/performance/default.aspx">performance</category><category domain="http://msmvps.com/blogs/omar/archive/tags/linq/default.aspx">linq</category><category domain="http://msmvps.com/blogs/omar/archive/tags/.net/default.aspx">.net</category></item><item><title>Solving common problems with Compiled Queries in Linq to Sql for high demand ASP.NET websites</title><link>http://msmvps.com/blogs/omar/archive/2008/10/27/solving-common-problems-with-compiled-queries-in-linq-to-sql-for-high-demand-asp-net-websites.aspx</link><pubDate>Mon, 27 Oct 2008 13:31:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1652150</guid><dc:creator>omar</dc:creator><slash:comments>16</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/omar/rsscomments.aspx?PostID=1652150</wfw:commentRss><comments>http://msmvps.com/blogs/omar/archive/2008/10/27/solving-common-problems-with-compiled-queries-in-linq-to-sql-for-high-demand-asp-net-websites.aspx#comments</comments><description>&lt;p&gt;If you are using Linq to SQL, instead of writing regular Linq Queries, you should be using &lt;a href="http://linqinaction.net/blogs/jwooley/archive/2007/09/04/linq-to-sql-compiled-queries.aspx"&gt;Compiled Queries&lt;/a&gt;. if you are building an ASP.NET web application that&amp;rsquo;s going to get thousands of hits per hour, the execution overhead of Linq queries is going to consume too much CPU and make your site slow. There&amp;rsquo;s a runtime cost associated with each and every Linq Query you write. The queries are parsed and converted to a nice SQL Statement on *every* hit. It&amp;rsquo;s not done at compile time because there&amp;rsquo;s no way to figure out what you might be sending as the parameters in the queries during runtime. So, if you have common Linq to Sql statements like the following one throughout your growing web application, you are soon going to have scalability nightmares:&lt;/p&gt;
&lt;div&gt;
&lt;pre class="csharpcode"&gt;var query = from widget &lt;span class="kwrd"&gt;in&lt;/span&gt; dc.Widgets&lt;br /&gt;                &lt;span class="kwrd"&gt;where&lt;/span&gt; widget.ID == id &amp;amp;&amp;amp; widget.PageID == pageId&lt;br /&gt;                select widget;&lt;br /&gt;&lt;br /&gt;var widget = query.SingleOrDefault();&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;There&amp;rsquo;s &lt;a href="http://www.jdconley.com/blog/archive/2007/11/28/linq-to-sql-surprise-performance-hit.aspx"&gt;a nice blog post by JD Conley&lt;/a&gt; that shows how evil Linq to Sql queries are:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_03BBB56F.png"&gt;&lt;img title="image" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_481BA6AE.png" border="0" height="389" width="654" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You see how many times &lt;span style="text-decoration:underline;"&gt;SqlVisitor.Visit&lt;/span&gt; is called to convert a Linq Query to its SQL representation? The runtime cost to convert a Linq query to its SQL Command representation is just way too high.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/ricom/archive/2008/01/14/performance-quiz-13-linq-to-sql-compiled-query-cost-solution.aspx"&gt;Rico Mariani has a very informative performance comparison&lt;/a&gt; of regular Linq queries vs Compiled Linq queries performance:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_6C608B30.png"&gt;&lt;img title="image" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_3BEA06BA.png" border="0" height="252" width="531" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Compiled Query wins on every case.&lt;/p&gt;
&lt;p&gt;So, now you know about the benefits of compiled queries. If you are building ASP.NET web application that is going to get high traffic and you have a lot of Linq to Sql queries throughout your project, you have to go for compiled queries. Compiled Queries are built for this specific scenario. &lt;/p&gt;
&lt;p&gt;In this article, I will show you some steps to convert regular Linq to Sql queries to their Compiled representation and how to avoid the dreaded exception &amp;ldquo;&lt;b&gt;Compiled queries across DataContexts with different LoadOptions not supported.&amp;rdquo;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Here are some step by step instruction on converting a Linq to Sql query to its compiled form:&lt;/p&gt;
&lt;p&gt;First we need to find out all the external decision factors in a query. It mostly means parameters in the WHERE clause. Say, we are trying to get a user from &lt;span style="text-decoration:underline;"&gt;aspnet_users&lt;/span&gt; table using Username and Application ID:&lt;/p&gt;
&lt;div&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_674E27B4.png"&gt;&lt;img title="Query to get a user from aspnet_users table" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" alt="Query to get a user from aspnet_users table" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_66098ED5.png" border="0" height="57" width="544" /&gt;&lt;/a&gt; &lt;/div&gt;
&lt;p&gt;Here, we have two external decision factor &amp;ndash; one is the Username and another is the Application ID. So, first think this way, if you were to wrap this query in a function that will just return this query as it is, what would you do? You would create a function that takes the &lt;span style="text-decoration:underline;"&gt;DataContext&lt;/span&gt; (dc named here), then two parameters named &lt;span style="text-decoration:underline;"&gt;userName&lt;/span&gt; and &lt;span style="text-decoration:underline;"&gt;applicationID,&lt;/span&gt; right?&lt;/p&gt;
&lt;p&gt;So, be it. We create one function that returns just this query:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_443DB644.png"&gt;&lt;img title="Converting a LInq Query to a function" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" alt="Converting a LInq Query to a function" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_4F1A978C.png" border="0" height="103" width="693" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Next step is to replace this function with a &lt;span style="text-decoration:underline;"&gt;Func&amp;lt;&amp;gt;&lt;/span&gt; representation that returns the query. This is the hard part. If you haven&amp;rsquo;t dealt with &lt;span style="text-decoration:underline;"&gt;Func&amp;lt;&amp;gt;&lt;/span&gt; and Lambda expression before, then I suggest you read &lt;a title="Lambda Expression" href="http://blogs.msdn.com/ericwhite/pages/Lambda-Expressions.aspx"&gt;this&lt;/a&gt; and &lt;a title="Lambda Expression" href="http://blah.winsmarts.com/2006/05/19/demystifying-c-30--part-4-lambda-expressions.aspx"&gt;this&lt;/a&gt; and then continue.&lt;/p&gt;
&lt;p&gt;So, here&amp;rsquo;s the delegate representation of the above function:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_262F8283.png"&gt;&lt;img title="Creating a delegate out of Linq Query" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" alt="Creating a delegate out of Linq Query" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_4F571AC1.png" border="0" height="114" width="573" /&gt;&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Couple of things to note here. I have declared the delegate as &lt;span style="text-decoration:underline;"&gt;static readonly&lt;/span&gt; because a compiled query is declared only once and reused by all threads. If you don&amp;rsquo;t declare Compiled Queries as static, then you don&amp;rsquo;t get the performance gain because compiling queries everytime when needed is even worse than regular Linq queries. &lt;/p&gt;
&lt;p&gt;Then there&amp;rsquo;s the complex &lt;span style="text-decoration:underline;"&gt;Func&amp;lt;DropthingsDataContext, string, Guid, IQueryable&amp;lt;aspnet_User&amp;gt;&amp;gt;&lt;/span&gt; thing. Basically the generic &lt;span style="text-decoration:underline;"&gt;Func&amp;lt;&amp;gt;&lt;/span&gt; is declared to have three parameters from the &lt;span style="text-decoration:underline;"&gt;GetQuery&lt;/span&gt; function and a return type of &lt;span style="text-decoration:underline;"&gt;IQueryable&amp;lt;aspnet_User&amp;gt;&lt;/span&gt;. Here the parameter types are specified so that the delegate is created strongly typed. &lt;span style="text-decoration:underline;"&gt;Func&amp;lt;&amp;gt;&lt;/span&gt; allows up to 4 parameters and 1 return type. &lt;/p&gt;
&lt;p&gt;Next comes the real business, compiling the query. Now that we have the query in delegate form, we can pass this to &lt;span style="text-decoration:underline;"&gt;CompiledQuery.Compile&lt;/span&gt; function which compiles the delegate and returns a handle to us. Instead of directly assigning the lambda expression to the func, we will pass the expression through the &lt;span style="text-decoration:underline;"&gt;CompiledQuery.Compile&lt;/span&gt; function.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_0D703573.png"&gt;&lt;img title="Converting a Linq Query to Compiled Query" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" alt="Converting a Linq Query to Compiled Query" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_093637E1.png" border="0" height="133" width="677" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s where head starts to spin. This is so hard to read and maintain. Bear with me. I just wrapped the lambda expression on the right side inside the &lt;span style="text-decoration:underline;"&gt;CompiledQuery.Compile&lt;/span&gt; function. Basically that&amp;rsquo;s the only change. Also, when you call &lt;span style="text-decoration:underline;"&gt;CompiledQuery.Compile&amp;lt;&amp;gt;&lt;/span&gt;, the generic types must match and be in exactly the same order as the &lt;span style="text-decoration:underline;"&gt;Func&amp;lt;&amp;gt;&lt;/span&gt; declaration.&lt;/p&gt;
&lt;p&gt;Fortunately, calling a compiled query is as simple as calling a function:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_42D8D1CB.png"&gt;&lt;img title="Running Compiled Query" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" alt="Running Compiled Query" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_3F773A23.png" border="0" height="89" width="716" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;There you have it, a lot faster Linq Query execution. The hard work of converting all your queries into Compiled Query pays off when you see the performance difference.&lt;/p&gt;
&lt;p&gt;Now, there are some challenges to Compiled Queries. Most common one is, what do you do when you have more than 4 parameters to supply to a Compiled Query? You can&amp;rsquo;t declare a &lt;span style="text-decoration:underline;"&gt;Func&amp;lt;&amp;gt;&lt;/span&gt; with more than 4 types. Solution is to use a &lt;span style="text-decoration:underline;"&gt;struct&lt;/span&gt; to encapsulate all the parameters. Here&amp;rsquo;s an example:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_2F87F55F.png"&gt;&lt;img title="Using struct in compiled query as parameter" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" alt="Using struct in compiled query as parameter" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_7CF4721F.png" border="0" height="245" width="736" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Calling the query is quite simple:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_7660F28F.png"&gt;&lt;img title="Calling compiled query with struct parameter" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" alt="Calling compiled query with struct parameter" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_575ACEF1.png" border="0" height="55" width="674" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now to the dreaded challenge of using &lt;span style="text-decoration:underline;"&gt;LoadOptions&lt;/span&gt; with Compiled Query. You will notice that the following code results in an exception:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_039755D6.png"&gt;&lt;img title="Using DataLoadOptions with Compiled Query" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" alt="Using DataLoadOptions with Compiled Query" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_2D4AAAFC.png" border="0" height="133" width="647" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The above &lt;span style="text-decoration:underline;"&gt;DataLoadOption&lt;/span&gt; runs perfectly when you use regular Linq Queries. But it does not work with compiled queries. When you run this code and the query hits the second time, it produces an exception:&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Compiled queries across DataContexts with different LoadOptions not supported&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;A compiled query remembers the &lt;span style="text-decoration:underline;"&gt;DataLoadOption&lt;/span&gt; once its called. It does not allow executing the same compiled query with a different &lt;span style="text-decoration:underline;"&gt;DataLoadOption&lt;/span&gt; again. Although you are creating the same &lt;span style="text-decoration:underline;"&gt;DataLoadOption&lt;/span&gt; with the same &lt;span style="text-decoration:underline;"&gt;LoadWith&amp;lt;&amp;gt;&lt;/span&gt; calls, it still produces exception because it remembers the exact instance that was used when the compiled query was called for the first time. Since next call creates a new instance of &lt;span style="text-decoration:underline;"&gt;DataLoadOptions&lt;/span&gt;, it does not match and the exception is thrown. You can read details about the problem in &lt;a title="Compiled Queries cannot take same DataLoadOption" href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2558764&amp;amp;SiteID=1"&gt;this forum post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The solution is to use a static &lt;span style="text-decoration:underline;"&gt;DataLoadOption&lt;/span&gt;. You cannot create a local &lt;span style="text-decoration:underline;"&gt;DataLoadOption&lt;/span&gt; instance and use in compiled queries. It needs to be &lt;span style="text-decoration:underline;"&gt;static&lt;/span&gt;. Here&amp;rsquo;s how you can do it:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_240E6FBB.png"&gt;&lt;img title="image" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_08F5A0AD.png" border="0" height="146" width="589" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Basically the idea is to construct a &lt;span style="text-decoration:underline;"&gt;static&lt;/span&gt; instance of &lt;span style="text-decoration:underline;"&gt;DataLoadOptions&lt;/span&gt; using a static function. As writing function for every single &lt;span style="text-decoration:underline;"&gt;DataLoadOptions&lt;/span&gt; combination is painful, I created a static delegate here and executed it right on the declaration line. This is in interesting way to declare a variable that requires more than one statement to prepare it. &lt;/p&gt;
&lt;p&gt;Using this option is very simple:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_4DC1C4E1.png"&gt;&lt;img title="image" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_4A602D39.png" border="0" height="73" width="670" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Now you can use &lt;span style="text-decoration:underline;"&gt;DataLoadOptions&lt;/span&gt; with compiled queries. &lt;/p&gt;
&lt;div class="wlWriterHeaderFooter" style="text-align:left;margin:0px;padding:4px 4px 4px 4px;"&gt;
&lt;script type="text/javascript"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;&lt;/script&gt;
&lt;script language="javascript" src="http://widgets.dzone.com/widgets/zoneit.js"&gt;&lt;/script&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fmsmvps.com%2fblogs%2fomar%2farchive%2f2008%2f10%2f27%2fsolving-common-problems-with-compiled-queries-in-linq-to-sql-for-high-demand-asp-net-websites.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fmsmvps.com%2fblogs%2fomar%2farchive%2f2008%2f10%2f27%2fsolving-common-problems-with-compiled-queries-in-linq-to-sql-for-high-demand-asp-net-websites.aspx" alt="kick it on DotNetKicks.com" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1652150" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/performance/default.aspx">performance</category><category domain="http://msmvps.com/blogs/omar/archive/tags/linq/default.aspx">linq</category><category domain="http://msmvps.com/blogs/omar/archive/tags/.net/default.aspx">.net</category></item><item><title>Deploy ASP.NET MVC on IIS 6, solve 404, compression and performance problems</title><link>http://msmvps.com/blogs/omar/archive/2008/06/30/deploy-asp-net-mvc-on-iis-6-solve-404-compression-and-performance-problems.aspx</link><pubDate>Mon, 30 Jun 2008 08:12:22 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1638845</guid><dc:creator>omar</dc:creator><slash:comments>21</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/omar/rsscomments.aspx?PostID=1638845</wfw:commentRss><comments>http://msmvps.com/blogs/omar/archive/2008/06/30/deploy-asp-net-mvc-on-iis-6-solve-404-compression-and-performance-problems.aspx#comments</comments><description>&lt;p&gt;There are several problems with ASP.NET MVC application when deployed on IIS 6.0:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Extensionless URLs give 404 unless some URL Rewrite module is used or wildcard mapping is enabled  &lt;li&gt;IIS 6.0 built-in compression does not work for dynamic requests. As a result, ASP.NET pages are served uncompressed resulting in poor site load speed.  &lt;li&gt;Mapping wildcard extension to ASP.NET introduces the following problems:  &lt;ul&gt; &lt;li&gt;Slow performance as all static files get handled by ASP.NET and ASP.NET reads the file from file system on every call  &lt;li&gt;Expires headers doesn&amp;#39;t work for static content as IIS does not serve them anymore. Learn about benefits of expires header from &lt;a title="Making best use of cache" href="http://msmvps.com/blogs/omar/archive/2007/11/29/making-best-use-of-cache-for-high-performance-website.aspx"&gt;here&lt;/a&gt;. ASP.NET serves a fixed expires header that makes content expire in a day.  &lt;li&gt;Cache-Control header does not produce max-age properly and thus caching does not work as expected. Learn about caching best practices from &lt;a title="Making best use of Cache" href="http://msmvps.com/blogs/omar/archive/2007/11/29/making-best-use-of-cache-for-high-performance-website.aspx"&gt;here&lt;/a&gt;. &lt;/li&gt;&lt;/ul&gt; &lt;li&gt;After deploying on a domain as the root site, the homepage produces HTTP 404.&lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;Problem 1: Visiting your website&amp;#39;s homepage gives 404 when hosted on a domain&lt;/h3&gt; &lt;p&gt;You have done the wildcard mapping, mapped .mvc extention to ASP.NET ISAPI handler, written the route mapping for Default.aspx or default.aspx (lowercase), but still when you visit your homepage after deployment, you get:&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_32.png"&gt;&lt;img style="border-right:0px;border-top:0px;border-left:0px;border-bottom:0px;" height="273" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_6.png" width="430" border="0" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;You will find people banging their heads on the wall here:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a title="http://forums.asp.net/t/1237051.aspx" href="http://forums.asp.net/t/1237051.aspx"&gt;http://forums.asp.net/t/1237051.aspx&lt;/a&gt;  &lt;li&gt;&lt;a title="http://forums.asp.net/t/1253599.aspx" href="http://forums.asp.net/t/1253599.aspx"&gt;http://forums.asp.net/t/1253599.aspx&lt;/a&gt;  &lt;li&gt;&lt;a title="http://forums.asp.net/p/1239943/2294813.aspx" href="http://forums.asp.net/p/1239943/2294813.aspx"&gt;http://forums.asp.net/p/1239943/2294813.aspx&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Solution is to capture hits going to &amp;quot;/&amp;quot; and then rewrite it to Default.aspx:&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_4.png"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="61" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_1.png" width="600" border="0" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;You can apply this approach to any URL that ASP.NET MVC is not handling for you and it should handle. Just see the URL reported on the 404 error page and then rewrite it to a proper URL.&lt;/p&gt; &lt;h3&gt;Problem 2: IIS 6 compression is no longer working after wildcard mapping&lt;/h3&gt; &lt;p&gt;When you enable wildcard mapping, IIS 6 compression no longer works for extensionless URL because IIS 6 does not see any extension which is defined in IIS Metabase. You can learn about IIS 6 compression feature and how to configure it properly from &lt;a title="IIS 6 Compression - quickest and effective way to do it" href="http://msmvps.com/blogs/omar/archive/2006/08/10/iis-6-compression-quickest-and-effective-way-to-do-it-for-asp-net-compression.aspx"&gt;my earlier post&lt;/a&gt;. &lt;/p&gt; &lt;p&gt;Solution is to use an HttpModule to do the compression for dynamic requests.&lt;/p&gt; &lt;h3&gt;Problem 3: ASP.NET ISAPI does not cache Static Files &lt;/h3&gt; &lt;p&gt;When ASP.NET&amp;#39;s &lt;u&gt;DefaultHttpHandler&lt;/u&gt; serves static files, it does not cache the files in-memory or in ASP.NET cache. As a result, every hit to static file results in a File read. Below is the decompiled code in &lt;u&gt;DefaultHttpHandler&lt;/u&gt; when it handles a static file. As you see here, it makes a file read on every hit and it only set the expiration to one day in future. Moreover, it generates &lt;u&gt;ETag&lt;/u&gt; for each file based on file&amp;#39;s modified date. For best caching efficiency, we need to get rid of that &lt;u&gt;ETag&lt;/u&gt;, produce an expiry date on far future (like 30 days), and produce &lt;u&gt;Cache-Control&lt;/u&gt; header which offers better control over caching.&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_12.png"&gt;&lt;img height="433" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_5.png" width="600" border="0" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;So, we need to write a custom static file handler that will cache small files like images, Javascripts, CSS, HTML and so on in ASP.NET cache and serve the files directly from cache instead of hitting the disk. Here are the steps:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Install an &lt;u&gt;HttpModule&lt;/u&gt; that installs a Compression Stream on &lt;u&gt;Response.Filter&lt;/u&gt; so that anything written on Response gets compressed. This serves dynamic requests.  &lt;li&gt;Replace ASP.NET&amp;#39;s &lt;u&gt;DefaultHttpHandler&lt;/u&gt; that listens on *.* for static files.  &lt;li&gt;Write our own Http Handler that will deliver compressed response for static resources like Javascript, CSS, and HTML. &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_6.png"&gt;&lt;img height="59" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_2.png" width="600" border="0" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Here&amp;#39;s the mapping in ASP.NET&amp;#39;s web.config for the &lt;u&gt;DefaultHttpHandler&lt;/u&gt;. You will have to replace this with your own handler in order to serve static files compressed and cached. &lt;/p&gt; &lt;h3&gt;Solution 1: An Http Module to compress dynamic requests&lt;/h3&gt; &lt;p&gt;First, you need to serve compressed responses that are served by the &lt;u&gt;MvcHandler&lt;/u&gt; or ASP.NET&amp;#39;s default Page Handler. The following &lt;u&gt;HttpCompressionModule&lt;/u&gt; hooks on the &lt;u&gt;Response.Filter&lt;/u&gt; and installs a &lt;u&gt;GZipStream&lt;/u&gt; or &lt;u&gt;DeflateStream&lt;/u&gt; on it so that whatever is written on the Response stream, it gets compressed.&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_8.png"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="393" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_3.png" width="596" border="0" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;These are formalities for a regular &lt;u&gt;HttpModule&lt;/u&gt;. The real hook is installed as below:&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_10.png"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="436" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_4.png" width="593" border="0" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Here you see we ignore requests that are handled by ASP.NET&amp;#39;s &lt;u&gt;DefaultHttpHandler&lt;/u&gt; and our own &lt;u&gt;StaticFileHandler&lt;/u&gt; that you will see in next section. After that, it checks whether the request allows content to be compressed. &lt;u&gt;Accept-Encoding&lt;/u&gt; header contains &amp;quot;gzip&amp;quot; or &amp;quot;deflate&amp;quot; or both when browser supports compressed content. So, when browser supports compressed content, a Response Filter is installed to compress the output.&lt;/p&gt; &lt;h3&gt;Solution 2: An Http Module to compress and cache static file requests&lt;/h3&gt; &lt;p&gt;Here&amp;#39;s how the handler works:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Hooks on *.* so that all unhandled requests get served by the handler  &lt;li&gt;Handles some specific files like js, css, html, graphics files. Anything else, it lets ASP.NET transmit it  &lt;li&gt;The extensions it handles itself, it caches the file content so that subsequent requests are served from cache  &lt;li&gt;It allows compression of some specific extensions like js, css, html. It does not compress graphics files or any other extension.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Let&amp;#39;s start with the handler code:&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_16.png"&gt;&lt;img height="230" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_7.png" width="600" border="0" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Here you will find the extensions the handler handles and the extensions it compresses. You should only put files that are text files in the COMPRESS_FILE_TYPES.&lt;/p&gt; &lt;p&gt;Now start handling each request from &lt;u&gt;BeginProcessRequest&lt;/u&gt;. &lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_18.png"&gt;&lt;img height="432" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_8.png" width="598" border="0" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Here you decide the compression mode based on &lt;u&gt;Accept-Encoding&lt;/u&gt; header. If browser does not support compression, do not perform any compression. Then check if the file being requested falls in one of the extensions that we support. If not, let ASP.NET handle it. You will see soon how.&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_20.png"&gt;&lt;img height="537" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_9.png" width="599" border="0" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Calculate the cache key based on the compression mode and the physical path of the file. This ensures that no matter what the URL requested, we have one cache entry for one physical file. Physical file path won&amp;#39;t be different for the same file. Compression mode is used in the cache key because we need to store different copy of the file&amp;#39;s content in ASP.NET cache based on Compression Mode. So, there will be one uncompressed version, a gzip compressed version and a deflate compressed version.&lt;/p&gt; &lt;p&gt;Next check if the file exits. If not, throw HTTP 404. Then create a memory stream that will hold the bytes for the file or the compressed content. Then read the file and write in the memory stream either directly or via a GZip or Deflate stream. Then cache the bytes in the memory stream and deliver to response. You will see the &lt;u&gt;ReadFileData&lt;/u&gt; and &lt;u&gt;CacheAndDeliver&lt;/u&gt; functions soon.&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_22.png"&gt;&lt;img height="385" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_10.png" width="600" border="0" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;This function delivers content directly from ASP.NET cache. The code is simple, read from cache and write to the response.&lt;/p&gt; &lt;p&gt;When the content is not available in cache, read the file bytes and store in a memory stream either as it is or compressed based on what compression mode you decided before:&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_24.png"&gt;&lt;img height="426" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_11.png" width="598" border="0" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Here bytes are read in chunk in order to avoid large amount of memory allocation. You could read the whole file in one shot and store in a byte array same as the size of the file length. But I wanted to save memory allocation. Do a performance test to figure out if reading in 8K chunk is not the best approach for you.&lt;/p&gt; &lt;p&gt;Now you have the bytes to write to the response. Next step is to cache it and then deliver it.&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_26.png"&gt;&lt;img height="284" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_12.png" width="600" border="0" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Now the two functions that you have seen several times and have been wondering what they do. Here they are:&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_28.png"&gt;&lt;img height="477" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_13.png" width="599" border="0" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&lt;u&gt;WriteResponse&lt;/u&gt; has no tricks, but &lt;u&gt;ProduceResponseHeader&lt;/u&gt; has much wisdom in it. First it turns off response buffering so that ASP.NET does not store the written bytes in any internal buffer. This saves some memory allocation. Then it produces proper cache headers to cache the file in browser and proxy for 30 days, ensures proxy revalidate the file after the expiry date and also produces the &lt;u&gt;Last-Modified&lt;/u&gt; date from the file&amp;#39;s last write time in UTC.&lt;/p&gt; &lt;h3&gt;How to use it&lt;/h3&gt; &lt;p&gt;Get the &lt;u&gt;HttpCompressionModule&lt;/u&gt; and &lt;u&gt;StaticFileHandler&lt;/u&gt; from: &lt;/p&gt; &lt;p&gt;&lt;a title="http://code.msdn.microsoft.com/fastmvc" href="http://code.msdn.microsoft.com/fastmvc"&gt;http://code.msdn.microsoft.com/fastmvc&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Then install them in &lt;u&gt;web.config&lt;/u&gt;. First you install the &lt;u&gt;StaticFileHandler&lt;/u&gt; by removing the existing mapping for path=&amp;quot;*&amp;quot; and then you install the &lt;u&gt;HttpCompressionModule&lt;/u&gt;.&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_30.png"&gt;&lt;img height="208" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_14.png" width="602" border="0" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;That&amp;#39;s it! Enjoy a faster and more responsive ASP.NET MVC website deployed on IIS 6.0.&lt;/p&gt;&lt;span class="sbmLink"&gt;&lt;span class="sbmLink"&gt; &lt;table cellspacing="1" cellpadding="1"&gt;  &lt;tr&gt; &lt;td class="sbmText"&gt;Share this post : &lt;/td&gt; &lt;td class="sbmDim"&gt;&lt;a class="sbmDim" title="Post it to del.icio.us" href="http://del.icio.us/post?url=http://msmvps.com/blogs/omar/archive/2008/06/30/deploy-asp-net-mvc-on-iis-6-solve-404-compression-and-performance-problems.aspx&amp;amp;;title=Deploy%20ASP.NET%20MVC%20on%20IIS%206,%20solve%20404,%20compression%20and%20performance%20problems" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliciou4.png" border="0" alt="" /&gt;del.icio.us&lt;/a&gt;  &lt;td class="sbmDim"&gt;&lt;a class="sbmDim" title="Post it to digg" href="http://digg.com/submit?phase=2&amp;amp;url=http://msmvps.com/blogs/omar/archive/2008/06/30/deploy-asp-net-mvc-on-iis-6-solve-404-compression-and-performance-problems.aspx&amp;amp;title=Deploy%20ASP.NET%20MVC%20on%20IIS%206,%20solve%20404,%20compression%20and%20performance%20problems" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/digg14.png" border="0" alt="" /&gt;digg&lt;/a&gt;  &lt;td class="sbmDim"&gt;&lt;a class="sbmDim" title="Post it to dotnetkicks" href="http://www.dotnetkicks.com/kick/?url=http://msmvps.com/blogs/omar/archive/2008/06/30/deploy-asp-net-mvc-on-iis-6-solve-404-compression-and-performance-problems.aspx&amp;amp;title=Deploy%20ASP.NET%20MVC%20on%20IIS%206,%20solve%20404,%20compression%20and%20performance%20problems" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/CropperCapture154.jpg" border="0" alt="" /&gt;dotnetkicks&lt;/a&gt;  &lt;td class="sbmDim"&gt;&lt;a class="sbmDim" title="Post it to furl" href="http://www.furl.net/store?s=f&amp;amp;to=0&amp;amp;u=http://msmvps.com/blogs/omar/archive/2008/06/30/deploy-asp-net-mvc-on-iis-6-solve-404-compression-and-performance-problems.aspx&amp;amp;ti=Deploy%20ASP.NET%20MVC%20on%20IIS%206,%20solve%20404,%20compression%20and%20performance%20problems" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/furl4.png" border="0" alt="" /&gt;furl&lt;/a&gt;  &lt;td class="sbmDim"&gt;&lt;a class="sbmDim" title="Post it to live" href="https://favorites.live.com/quickadd.aspx?marklet=1&amp;amp;mkt=en-us&amp;amp;url=http://msmvps.com/blogs/omar/archive/2008/06/30/deploy-asp-net-mvc-on-iis-6-solve-404-compression-and-performance-problems.aspx&amp;amp;title=Deploy%20ASP.NET%20MVC%20on%20IIS%206,%20solve%20404,%20compression%20and%20performance%20problems" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/live4.png" border="0" alt="" /&gt;live&lt;/a&gt;  &lt;td class="sbmDim"&gt;&lt;a class="sbmDim" title="Post it to reddit!" href="http://reddit.com/submit?url=http://msmvps.com/blogs/omar/archive/2008/06/30/deploy-asp-net-mvc-on-iis-6-solve-404-compression-and-performance-problems.aspx&amp;amp;title=Deploy%20ASP.NET%20MVC%20on%20IIS%206,%20solve%20404,%20compression%20and%20performance%20problems" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/reddit4.png" border="0" alt="" /&gt;reddit&lt;/a&gt;  &lt;td class="sbmDim"&gt;&lt;a class="sbmDim" title="Post it to spurl" href="http://www.spurl.net/spurl.php?v=3&amp;amp;url=http://msmvps.com/blogs/omar/archive/2008/06/30/deploy-asp-net-mvc-on-iis-6-solve-404-compression-and-performance-problems.aspx&amp;amp;title=Deploy%20ASP.NET%20MVC%20on%20IIS%206,%20solve%20404,%20compression%20and%20performance%20problems" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/spurl8.png" border="0" alt="" /&gt;spurl&lt;/a&gt;  &lt;td class="sbmDim"&gt;&lt;a class="sbmDim" title="Post it to technorati!" href="http://technorati.com/faves/?add=http://msmvps.com/blogs/omar/archive/2008/06/30/deploy-asp-net-mvc-on-iis-6-solve-404-compression-and-performance-problems.aspx&amp;amp;title=Deploy%20ASP.NET%20MVC%20on%20IIS%206,%20solve%20404,%20compression%20and%20performance%20problems" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/technora4.png" border="0" alt="" /&gt;technorati&lt;/a&gt;  &lt;td class="sbmDim"&gt;&lt;a class="sbmDim" title="Post it to yahoo!" href="http://myweb.yahoo.com/myresults/bookmarklet?u=http://msmvps.com/blogs/omar/archive/2008/06/30/deploy-asp-net-mvc-on-iis-6-solve-404-compression-and-performance-problems.aspx&amp;amp;t=Deploy%20ASP.NET%20MVC%20on%20IIS%206,%20solve%20404,%20compression%20and%20performance%20problems" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/yahoo9.png" border="0" alt="" /&gt;yahoo&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;p&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fmsmvps.com%2fblogs%2fomar%2farchive%2f2008%2f06%2f30%2fdeploy-asp-net-mvc-on-iis-6-solve-404-compression-and-performance-problems.aspx"&gt;&lt;img alt="kick it on DotNetKicks.com" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fmsmvps.com%2fblogs%2fomar%2farchive%2f2008%2f06%2f30%2fdeploy-asp-net-mvc-on-iis-6-solve-404-compression-and-performance-problems.aspx" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1638845" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/performance/default.aspx">performance</category><category domain="http://msmvps.com/blogs/omar/archive/tags/asp.net/default.aspx">asp.net</category><category domain="http://msmvps.com/blogs/omar/archive/tags/production/default.aspx">production</category><category domain="http://msmvps.com/blogs/omar/archive/tags/.net/default.aspx">.net</category><category domain="http://msmvps.com/blogs/omar/archive/tags/asp.net+MVC/default.aspx">asp.net MVC</category></item><item><title>Fast, Streaming AJAX proxy - continuously download from cross domain</title><link>http://msmvps.com/blogs/omar/archive/2008/04/14/fast-streaming-ajax-proxy-continuously-download-from-cross-domain.aspx</link><pubDate>Mon, 14 Apr 2008 07:29:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1586081</guid><dc:creator>omar</dc:creator><slash:comments>15</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/omar/rsscomments.aspx?PostID=1586081</wfw:commentRss><comments>http://msmvps.com/blogs/omar/archive/2008/04/14/fast-streaming-ajax-proxy-continuously-download-from-cross-domain.aspx#comments</comments><description>&lt;p&gt;&lt;span id="intelliTXT"&gt;Due to browser&amp;#39;s prohibition on cross domain
XMLHTTP call, all AJAX
websites must have server side proxy to fetch content from external
domain like Flickr or Digg. From client side javascript code, an
XMLHTTP call goes to the server side proxy hosted on the same domain
and then the proxy downloads the content from the external server and
sends back to the browser. In general, all AJAX websites on the
Internet that are showing content from external domains are following
this proxy approach except some rare ones who are using JSONP. Such a
proxy gets a very large number of hits when a lot of component on the
website are downloading content from external domains. So, it becomes a
scalability issue when the proxy starts getting millions of hits.
Moreover, web page&amp;#39;s overall load performance largely depends on the
performance of the proxy as it delivers content to the page. In this
article, we will take a look how we can take a conventional AJAX Proxy
and make it faster, asynchronous, continuously stream content and thus
make it more scalable.&lt;/span&gt; &lt;/p&gt; &lt;p&gt;You can see such a proxy in action when you go to &lt;a href="http://www.pageflakes.com/"&gt;Pageflakes.com&lt;/a&gt;. You will see flakes (widgets) loading many different content like weather feed, flickr photo, youtube videos, RSS from many different external domains. All these are done via a &lt;i&gt;Content Proxy&lt;/i&gt;. Content Proxy served about &lt;b&gt;42.3 million URLs&lt;/b&gt; last month which is quite an engineering challenge for us to make it both fast and scalable. Sometimes Content Proxy serves megabytes of data, which poses even greater engineering challenge. As such proxy gets large number of hits, if we can save on an average 100ms from each call, we can save &lt;b&gt;4.23 million seconds&lt;/b&gt; of download/upload/processing time every month. That&amp;#39;s about 1175 man hours wasted throughout the world by millions of people staring at browser waiting for content to download.&lt;/p&gt; &lt;p&gt;Such a content proxy takes an external server&amp;#39;s URL as a query parameter. It downloads the content from the URL and then writes the content as response back to browser. &lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/WindowsLiveWriter/FastStreamingAJAXproxy_A628/image1.png"&gt;&lt;img src="http://msmvps.com/blogs/omar/WindowsLiveWriter/FastStreamingAJAXproxy_A628/image1_thumb.png" alt="image" border="0" height="107" width="532" /&gt;&lt;/a&gt;&lt;br /&gt;Figure: Content Proxy working as a middleman between browser and external domain &lt;/p&gt; &lt;p&gt;The above timeline shows how request goes to the server and then server makes a request to external server, downloads the response and then transmits back to the browser. The response arrow from proxy to browser is larger than the response arrow from external server to proxy because generally proxy server&amp;#39;s hosting environment has better download speed than the user&amp;#39;s Internet connectivity.&lt;/p&gt; &lt;p&gt;Such a content proxy is also available in my open source Ajax Web Portal &lt;a href="http://www.dropthings.com/"&gt;Dropthings.com&lt;/a&gt;. You can see from &lt;a href="http://www.codeplex.com/dropthings"&gt;its code&lt;/a&gt; how such a proxy is implemented.&lt;/p&gt; &lt;p&gt;The following is a very simple synchronous, non-streaming, blocking Proxy:&lt;/p&gt; &lt;div class="csharpcode-wrapper" style="width:94.38%;height:192px;"&gt;&lt;pre class="csharpcode" style="width:63.65%;height:176px;"&gt;[WebMethod]&lt;br /&gt;[ScriptMethod(UseHttpGet=&lt;span class="kwrd"&gt;true&lt;/span&gt;)]&lt;br /&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; GetString(&lt;span class="kwrd"&gt;string&lt;/span&gt; url)&lt;br /&gt;{&lt;br /&gt;        &lt;span class="kwrd"&gt;using&lt;/span&gt; (WebClient client = &lt;span class="kwrd"&gt;new&lt;/span&gt; WebClient())&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;string&lt;/span&gt; response = client.DownloadString(url);&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; response;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Although it shows the general principle, but it&amp;#39;s no where close to a real proxy because:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It&amp;#39;s a synchronous proxy and thus not scalable. Every call to this web method causes the ASP.NET thread to wait until the call to the external URL completes. 
&lt;/li&gt;&lt;li&gt;It&amp;#39;s &lt;b&gt;non streaming&lt;/b&gt;. It first downloads the entire content on the server, storing it in a string and then uploading that entire content to the browser. If you pass &lt;a href="http://msdn.microsoft.com/rss.xml"&gt;MSDN feed URL&lt;/a&gt;, it will download that gigantic 220 KB RSS XML on the server and store it on a 220 KB long string (actually double the size as .NET strings are all Unicode string) and then write 220 KB to&amp;nbsp; ASP.NET Response buffer, consuming another 220 KB UTF8 byte array in memory. Then that 220 KB will be passed to IIS in chunks so that it can transmit it to the browser. 
&lt;/li&gt;&lt;li&gt;It does not produce proper response header to cache the response on the server. Nor does it deliver important headers like &lt;i&gt;Content-Type&lt;/i&gt; from the source. 
&lt;/li&gt;&lt;li&gt;If external URL is providing gzipped content, it decompresses the content into a string representation and thus wastes server memory. 
&lt;/li&gt;&lt;li&gt;It does not cache the content on the server. So, repeated call to the same external URL within the same second or minute will download content from the external URL and thus waste bandwidth on your server. &lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;So, we need an asynchronous &lt;b&gt;streaming proxy&lt;/b&gt; that transmits the content to the browser while it downloads from the external domain server. So, it will download bytes from external URL in small chunks and immediately transmit that to the browser. As a result, browser will see a continuous transmission of bytes right after calling the web service. There will be no delay while the content is fully downloaded on the server.&lt;/p&gt;
&lt;p&gt;Before I show you the complex streaming proxy code, let&amp;#39;s take an evolutionary approach. Let&amp;#39;s build a better Content Proxy that the one shown above, which is synchronous, non-streaming but does not have the other problems mentioned above. We will build a HTTP Handler named &lt;u&gt;RegularProxy.ashx&lt;/u&gt; which will take &lt;u&gt;url&lt;/u&gt; as a query parameter. It will also take &lt;u&gt;cache&lt;/u&gt; as a query parameter which it will use to produce proper response headers in order to cache the content on the browser. Thus it will save browser from downloading the same content again and again.&lt;/p&gt;
&lt;div&gt;&lt;pre class="csharpcode"&gt;&amp;lt;%@ WebHandler Language=&lt;span class="str"&gt;&amp;quot;C#&amp;quot;&lt;/span&gt; Class=&lt;span class="str"&gt;&amp;quot;RegularProxy&amp;quot;&lt;/span&gt; %&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web.Caching;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Net;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; ProxyHelpers;&lt;br /&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; RegularProxy : IHttpHandler {&lt;br /&gt;        &lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ProcessRequest (HttpContext context) {&lt;br /&gt;        &lt;span class="kwrd"&gt;string&lt;/span&gt; url = context.Request[&lt;span class="str"&gt;&amp;quot;url&amp;quot;&lt;/span&gt;];&lt;br /&gt;        &lt;span class="kwrd"&gt;int&lt;/span&gt; cacheDuration = Convert.ToInt32(context.Request[&lt;span class="str"&gt;&amp;quot;cache&amp;quot;&lt;/span&gt;]?? &lt;span class="str"&gt;&amp;quot;0&amp;quot;&lt;/span&gt;);&lt;br /&gt;        &lt;span class="kwrd"&gt;string&lt;/span&gt; contentType = context.Request[&lt;span class="str"&gt;&amp;quot;type&amp;quot;&lt;/span&gt;];&lt;br /&gt;&lt;br /&gt;        &lt;span class="rem"&gt;// We don&amp;#39;t want to buffer because we want to save memory&lt;/span&gt;&lt;br /&gt;        context.Response.Buffer = &lt;span class="kwrd"&gt;false&lt;/span&gt;;&lt;br /&gt;            &lt;br /&gt;        &lt;span class="rem"&gt;// Serve from cache if available&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (context.Cache[url] != &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br /&gt;        {&lt;br /&gt;            context.Response.BinaryWrite(context.Cache[url] &lt;span class="kwrd"&gt;as&lt;/span&gt; &lt;span class="kwrd"&gt;byte&lt;/span&gt;[]);&lt;br /&gt;            context.Response.Flush();&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt;;&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="kwrd"&gt;using&lt;/span&gt; (WebClient client = &lt;span class="kwrd"&gt;new&lt;/span&gt; WebClient())&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (!&lt;span class="kwrd"&gt;string&lt;/span&gt;.IsNullOrEmpty(contentType))&lt;br /&gt;                client.Headers[&lt;span class="str"&gt;&amp;quot;Content-Type&amp;quot;&lt;/span&gt;] = contentType;&lt;br /&gt;            &lt;br /&gt;            client.Headers[&lt;span class="str"&gt;&amp;quot;Accept-Encoding&amp;quot;&lt;/span&gt;] = &lt;span class="str"&gt;&amp;quot;gzip&amp;quot;&lt;/span&gt;;&lt;br /&gt;            client.Headers[&lt;span class="str"&gt;&amp;quot;Accept&amp;quot;&lt;/span&gt;] = &lt;span class="str"&gt;&amp;quot;*/*&amp;quot;&lt;/span&gt;;&lt;br /&gt;            client.Headers[&lt;span class="str"&gt;&amp;quot;Accept-Language&amp;quot;&lt;/span&gt;] = &lt;span class="str"&gt;&amp;quot;en-US&amp;quot;&lt;/span&gt;;&lt;br /&gt;            client.Headers[&lt;span class="str"&gt;&amp;quot;User-Agent&amp;quot;&lt;/span&gt;] = &lt;br /&gt;&lt;span class="str"&gt;&amp;quot;Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6&amp;quot;&lt;/span&gt;;&lt;br /&gt;            &lt;br /&gt;            &lt;span class="kwrd"&gt;byte&lt;/span&gt;[] data = client.DownloadData(url);&lt;br /&gt;&lt;br /&gt;            context.Cache.Insert(url, data, &lt;span class="kwrd"&gt;null&lt;/span&gt;,&lt;br /&gt;                        Cache.NoAbsoluteExpiration,&lt;br /&gt;                        TimeSpan.FromMinutes(cacheDuration),&lt;br /&gt;                        CacheItemPriority.Normal, &lt;span class="kwrd"&gt;null&lt;/span&gt;); &lt;br /&gt;            &lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (!context.Response.IsClientConnected) &lt;span class="kwrd"&gt;return&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;br /&gt;            &lt;span class="rem"&gt;// Deliver content type, encoding and length as it is received from the external URL&lt;/span&gt;&lt;br /&gt;            context.Response.ContentType = client.ResponseHeaders[&lt;span class="str"&gt;&amp;quot;Content-Type&amp;quot;&lt;/span&gt;];&lt;br /&gt;            &lt;span class="kwrd"&gt;string&lt;/span&gt; contentEncoding = client.ResponseHeaders[&lt;span class="str"&gt;&amp;quot;Content-Encoding&amp;quot;&lt;/span&gt;];&lt;br /&gt;            &lt;span class="kwrd"&gt;string&lt;/span&gt; contentLength = client.ResponseHeaders[&lt;span class="str"&gt;&amp;quot;Content-Length&amp;quot;&lt;/span&gt;];&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (!&lt;span class="kwrd"&gt;string&lt;/span&gt;.IsNullOrEmpty(contentEncoding))&lt;br /&gt;                context.Response.AppendHeader(&lt;span class="str"&gt;&amp;quot;Content-Encoding&amp;quot;&lt;/span&gt;, contentEncoding);&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (!&lt;span class="kwrd"&gt;string&lt;/span&gt;.IsNullOrEmpty(contentLength))&lt;br /&gt;                context.Response.AppendHeader(&lt;span class="str"&gt;&amp;quot;Content-Length&amp;quot;&lt;/span&gt;, contentLength);&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (cacheDuration &amp;gt; 0)&lt;br /&gt;                HttpHelper.CacheResponse(context, cacheDuration);&lt;br /&gt;            &lt;br /&gt;            &lt;span class="rem"&gt;// Transmit the exact bytes downloaded&lt;/span&gt;&lt;br /&gt;            context.Response.BinaryWrite(data);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt; &lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; IsReusable {&lt;br /&gt;        get {&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;false&lt;/span&gt;;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There are two enhancements in this proxy:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It allows server side caching of content. Same URL requested by a different browser within a time period will not be downloaded on server again, instead it will be served from cache. 
&lt;/li&gt;&lt;li&gt;It generates proper response cache header so that the content can be cached on browser. 
&lt;/li&gt;&lt;li&gt;It does not decompress the downloaded content in memory. It keeps the original byte stream intact. This saves memory allocation. 
&lt;/li&gt;&lt;li&gt;It transmits the data in non-buffered fashion, which means ASP.NET Response object does not buffer the response and thus saves memory&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;However, this is a blocking proxy. We need to make a streaming asynchronous proxy for better performance. Here&amp;#39;s why:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/WindowsLiveWriter/FastStreamingAJAXproxy_A628/image_8.png"&gt;&lt;img src="http://msmvps.com/blogs/omar/WindowsLiveWriter/FastStreamingAJAXproxy_A628/image_thumb_3.png" alt="image" border="0" height="128" width="497" /&gt;&lt;/a&gt;&amp;nbsp;&lt;br /&gt;Figure: Continuous streaming proxy&lt;/p&gt;
&lt;p&gt;As you see, when data is transmitted from server to browser while server downloads the content, the delay for server side download is eliminated. So, if server takes 300ms to download something from external source, and then 700ms to send it back to browser, you can save up to 300ms Network Latency between server and browser. The situation gets even better when the external server that serves the content is slow and takes quite some time to deliver the content. The slower external site is, the more saving you get in this continuous streaming approach. This is significantly faster than blocking approach when the external server is in Asia or Australia and your server is in USA. &lt;/p&gt;
&lt;p&gt;The approach for continuous proxy is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Read bytes from external server in chunks of 8KB from a separate thread (Reader thread) so that it&amp;#39;s not blocked 
&lt;/li&gt;&lt;li&gt;Store the chunks in an in-memory Queue 
&lt;/li&gt;&lt;li&gt;Write the chunks to ASP.NET Response from that same queue 
&lt;/li&gt;&lt;li&gt;If the queue is finished, wait until more bytes are downloaded by the reader thread&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/WindowsLiveWriter/FastStreamingAJAXproxy_A628/image15.png"&gt;&lt;img src="http://msmvps.com/blogs/omar/WindowsLiveWriter/FastStreamingAJAXproxy_A628/image15_thumb.png" alt="image" border="0" height="180" width="551" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;The Pipe Stream needs to be thread safe and it needs to support blocking Read. By blocking read it means, if a thread tries to read a chunk from it and the stream is empty, it will suspend that thread until another thread writes something on the stream. Once a write happens, it will resume the reader thread and allow it to read. I have taken the code of &lt;u&gt;PipeStream&lt;/u&gt; from &lt;a href="http://www.codeproject.com/KB/threads/PipeStream.aspx"&gt;CodeProject article by James Kolpack&lt;/a&gt; and extended it to make sure it&amp;#39;s high performance, supports chunks of bytes to be stored instead of single bytes, support timeout on waits and so on. &lt;/p&gt;
&lt;p&gt;A did some comparison between Regular proxy (blocking, synchronous, download all then deliver) and Streaming Proxy (continuous transmission from external server to browser). Both proxy downloads the MSDN feed and delivers it to the browser. The time taken here shows the total duration of browser making the request to the proxy and then getting the entire response.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/WindowsLiveWriter/FastStreamingAJAXproxy_A628/image_14.png"&gt;&lt;img src="http://msmvps.com/blogs/omar/WindowsLiveWriter/FastStreamingAJAXproxy_A628/image_thumb_4.png" alt="image" border="0" height="230" width="381" /&gt;&lt;/a&gt; &lt;br /&gt;Figure: Time taken by Streaming Proxy vs Regular Proxy while downloading MSDN feed&lt;/p&gt;
&lt;p&gt;Not a very scientific graph and response time varies on the link speed between the browser and the proxy server and then from proxy server to the external server. But it shows that most of the time, Streaming Proxy outperformed Regular proxy.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/WindowsLiveWriter/FastStreamingAJAXproxy_A628/image_18.png"&gt;&lt;img src="http://msmvps.com/blogs/omar/WindowsLiveWriter/FastStreamingAJAXproxy_A628/image_thumb_7.png" alt="image" border="0" height="373" width="457" /&gt;&lt;/a&gt; &lt;br /&gt;Figure: Test client to compare between Regular Proxy and Streaming Proxy&lt;/p&gt;
&lt;p&gt;You can also test both proxy&amp;#39;s response time by going to &lt;a href="http://labs.dropthings.com/AjaxStreamingProxy"&gt;http://labs.dropthings.com/AjaxStreamingProxy&lt;/a&gt;. Put your URL and hit Regular/Stream button and see the &amp;quot;Statistics&amp;quot; text box for the total duration. You can turn on &amp;quot;Cache response&amp;quot; and hit a URL from one browser. Then go to another browser and hit the URL to see the response coming from server cache directly. Also if you hit the URL again on the same browser, you will see response comes instantly without ever making call to the server. That&amp;#39;s browser cache at work.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Learn more about Http Response caching from my blog post:&lt;br /&gt;&lt;a href="http://feeds.feedburner.com/%7Er/OmarAlZabirBlog/%7E3/267239050/making-best-use-of-cache-for-high-performance-website.aspx"&gt;Making best use of cache for high performance website&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;h3&gt;&lt;/h3&gt;
&lt;p&gt;A Visual Studio Web Test run inside a Load Test shows a better picture:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/WindowsLiveWriter/FastStreamingAJAXproxy_A628/image_24.png"&gt;&lt;img src="http://msmvps.com/blogs/omar/WindowsLiveWriter/FastStreamingAJAXproxy_A628/image_thumb_10.png" alt="image" border="0" height="200" width="512" /&gt;&lt;/a&gt;&amp;nbsp;&lt;br /&gt;Figure: Regular Proxy load test result shows &lt;b&gt;Average Requests/Sec 0.79&lt;/b&gt; and &lt;b&gt;Avg Response Time 2.5 sec&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/WindowsLiveWriter/FastStreamingAJAXproxy_A628/image_26.png"&gt;&lt;img src="http://msmvps.com/blogs/omar/WindowsLiveWriter/FastStreamingAJAXproxy_A628/image_thumb_11.png" alt="image" border="0" height="214" width="506" /&gt;&lt;/a&gt;&lt;br /&gt;Figure: Streaming Proxy load test result shows &lt;b&gt;Avg Req/Sec is 1.08&lt;/b&gt; and &lt;b&gt;Avg Response Time 1.8 sec&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;From the above load test results, Streaming Proxy is &lt;b&gt;26% better Request/Sec and Average Response Time is 29% better&lt;/b&gt;. The numbers may sound small, but at Pageflakes, 29% better response time means &lt;b&gt;1.29 million seconds&lt;/b&gt; saved per month for all the users on the website. So, we are effectively saving 353 man hours per month which was wasted staring at browser screen while it downloads content.&lt;/p&gt;
&lt;h3&gt;Building the Streaming Proxy&lt;/h3&gt;&lt;p&gt;The details how the Streaming Proxy is built is quite long and not suitable for a blog post. So, I have written a CodeProject article:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.codeproject.com/KB/ajax/ajaxproxy.aspx"&gt;Fast, Scalable, Streaming AJAX Proxy - continuously deliver data from cross domain&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Please read the article and please vote for me if your find it useful. &amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1586081" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/performance/default.aspx">performance</category><category domain="http://msmvps.com/blogs/omar/archive/tags/asp.net+ajax/default.aspx">asp.net ajax</category><category domain="http://msmvps.com/blogs/omar/archive/tags/asp.net/default.aspx">asp.net</category><category domain="http://msmvps.com/blogs/omar/archive/tags/pageflakes/default.aspx">pageflakes</category><category domain="http://msmvps.com/blogs/omar/archive/tags/ajax/default.aspx">ajax</category><category domain="http://msmvps.com/blogs/omar/archive/tags/.net/default.aspx">.net</category></item><item><title>Desktop RSS Feed Aggregator client with Outlook Integration</title><link>http://msmvps.com/blogs/omar/archive/2008/02/05/desktop-rss-feed-aggregator-client-with-outlook-integration.aspx</link><pubDate>Tue, 05 Feb 2008 13:10:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1497209</guid><dc:creator>omar</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/omar/rsscomments.aspx?PostID=1497209</wfw:commentRss><comments>http://msmvps.com/blogs/omar/archive/2008/02/05/desktop-rss-feed-aggregator-client-with-outlook-integration.aspx#comments</comments><description>&lt;p&gt;Back in 2005, I built an open source RSS Feed Aggregator Desktop client which has been quite popular since its release. It has 48,672 downloads so far. From the activity I see on sourceforge statistics, it&amp;#39;s being used about 20,000 times per day.&lt;/p&gt; &lt;p&gt;&lt;a href="http://rssfeederdotnet.sourceforge.net/"&gt;http://rssfeederdotnet.sourceforge.net/&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;b&gt;What is RSS Feeder.NET&lt;/b&gt;&lt;/p&gt; &lt;p&gt;RSS Feeder.NET is a free open source desktop RSS feed aggregator which downloads feeds from web sources and stores locally for offline viewing, searching and processing. It is also a rich blogging tool which you can use to blog to variety of blog engines including WordPress, B2Evolution, .Text, Community Server etc. You can be fully MS Outlook® dependent or can run fully standalone. You can also use both at the same time whichever you find comfortable to work with. It does not increase Outlook load time, nor does it make Outlook slow frequently or prevent from closing properly. It is a Smart Client that makes best use of both Local Resource and Distributed Web Information sources.&lt;/p&gt; &lt;p&gt;&lt;a href="http://prdownloads.sourceforge.net/rssfeederdotnet/RSSFeederSetup_3_3.msi?download" target="_blank"&gt;Download Installer ver 3.3 (Nov 10, 2005)&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://prdownloads.sourceforge.net/rssfeederdotnet/RSSFeeder_src_3_3.zip?download" target="_blank"&gt;Download Source Code ver 3.3 (Nov 10, 2005)&lt;/a&gt;&lt;/p&gt;Here’s an Article which explains how it is developed: &lt;br /&gt;&lt;a href="http://www.codeproject.com/smartclient/rssfeeder.asp"&gt;A RSS Feed Aggregator &amp;amp; Blog Smart Client&lt;/a&gt;  &lt;p&gt;Features:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;b&gt;Newspaper mode. &lt;/b&gt;You can read feeds in a more readable newspaper mode called “Blogpaper”  &lt;/li&gt;&lt;li&gt;&lt;b&gt;Auto Discovery&lt;/b&gt;. Drag any hyper link and I will find out whether there is any RSS Feed in that page  &lt;/li&gt;&lt;li&gt;&lt;b&gt;Outlook integration&lt;/b&gt;. You can store feeds in Outlook folders  &lt;/li&gt;&lt;li&gt;&lt;b&gt;Blogging. &lt;/b&gt;It provides you a Outlook 2003 style convenient workspace to manage your blog accounts and write rich posts  &lt;/li&gt;&lt;li&gt;&lt;b&gt;Blog from Outlook.&lt;/b&gt; You can specify an Outlook folder for a weblog account. All the posts from that folder is automatically posted to the weblog during synchronization. You can write posts as HTML using Word editor. Post content (HTML markup) is cleaned rigorously before posting to the weblog.  &lt;/li&gt;&lt;li&gt;&lt;b&gt;Outlook View. &lt;/b&gt;It uses a customized view to present a more readable list of feeds in Outlook Folders. The standard Post view is not easy to browse through quickly. The view puts the subject first in bold and an excerpt of the post under the subject.  &lt;/li&gt;&lt;li&gt;&lt;b&gt;Optimized Startup&lt;/b&gt;. You can safely put RSS Feeder at startup and it won’t make your Windows® start slower. A clever lazy loading process puts no effort on Windows® during startup instead starts the app when Windows® has finally regained its strength after the long boot up struggle.  &lt;/li&gt;&lt;li&gt;&lt;b&gt;Newsgator Import. &lt;/b&gt;Newsgator users can use RSS Feeder to import all the subscriptions and seamlessly replace Newsgator without any modification to Outlook folder locations. &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;b&gt;Browse Mode&lt;/b&gt; &lt;br /&gt;&lt;br /&gt;&lt;img src="http://rssfeederdotnet.sourceforge.net/screenshots/MainView.JPG" alt="Main View" /&gt;&lt;/p&gt; &lt;p&gt;&lt;b&gt;Blogpaper mode&lt;/b&gt; &lt;br /&gt;&lt;br /&gt;&lt;img src="http://rssfeederdotnet.sourceforge.net/screenshots/BlogPaper.JPG" alt="Blogpaper mode" /&gt;&lt;/p&gt; &lt;p&gt;&lt;b&gt;Outlook 2003 View&lt;/b&gt; &lt;br /&gt;&lt;br /&gt;&lt;img src="http://rssfeederdotnet.sourceforge.net/screenshots/OutlokView.JPG" alt="Outlook 2003 View" /&gt;&lt;/p&gt; &lt;p&gt;&lt;b&gt;Tray Application&lt;/b&gt; &lt;br /&gt;&lt;br /&gt;&lt;img src="http://rssfeederdotnet.sourceforge.net/screenshots/RSS%20Server.JPG" alt="RSS Server" /&gt;&lt;/p&gt; &lt;p&gt;&lt;b&gt;Blog Module&lt;/b&gt; &lt;br /&gt;&lt;br /&gt;&lt;img src="http://rssfeederdotnet.sourceforge.net/screenshots/Blog.JPG" alt="Blog" /&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1497209" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/misc/default.aspx">misc</category><category domain="http://msmvps.com/blogs/omar/archive/tags/.net/default.aspx">.net</category></item><item><title>10 ASP.NET Performance and Scalability Secrets</title><link>http://msmvps.com/blogs/omar/archive/2008/01/30/10-asp-net-performance-and-scalability-secrets.aspx</link><pubDate>Wed, 30 Jan 2008 15:47:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1486901</guid><dc:creator>omar</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/omar/rsscomments.aspx?PostID=1486901</wfw:commentRss><comments>http://msmvps.com/blogs/omar/archive/2008/01/30/10-asp-net-performance-and-scalability-secrets.aspx#comments</comments><description>&lt;p&gt;ASP.NET 2.0 has many secrets, when revealed, can give you big performance and
scalability boost. For instance, there are secret bottlenecks in Membership and Profile
provider which can be solved easily to make authentication and authorization faster.
Furthermore, ASP.NET Http pipeline can be tweaked to avoid executing unnecessary code
that gets hit on each and every request. Not only that, ASP.NET Worker Process can be
pushed to its limit to squeeze out every drop of performance out of it. Page fragment
output caching on the browser (not on the server) can save significant amount of download
time on repeated visits. On demand UI loading can give your site a fast and smooth
feeling. Finally, Content Delivery Networks (CDN) and proper use of HTTP Cache headers
can make your website screaming fast when implemented properly. In this article, you will
learn these techniques that can give your ASP.NET application a big performance and
scalability boost and prepare it to perform well under 10 times to 100 times more
traffic.&lt;/p&gt;
&lt;p&gt;
&lt;a title="http://www.codeproject.com/KB/aspnet/10ASPNetPerformance.aspx" href="http://www.codeproject.com/KB/aspnet/10ASPNetPerformance.aspx"&gt;http://www.codeproject.com/KB/aspnet/10ASPNetPerformance.aspx&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;In this article I have shown the following techniques:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ASP.NET Pipeline optimization&lt;/li&gt;
&lt;li&gt;ASP.NET Process configuration optimization&lt;/li&gt;
&lt;li&gt;Things you must do for ASP.NET before going live&lt;/li&gt;
&lt;li&gt;Content Delivery Network&lt;/li&gt;
&lt;li&gt;Caching AJAX calls on browser&lt;/li&gt;
&lt;li&gt;Making best use of Browser Cache&lt;/li&gt;
&lt;li&gt;On demand progressive UI loading for fast smooth experience&lt;/li&gt;
&lt;li&gt;Optimize ASP.NET 2.0 Profile provider&lt;/li&gt;
&lt;li&gt;How to query ASP.NET 2.0 Membership tables without bringing down the site&lt;/li&gt;
&lt;li&gt;Prevent Denial of Service (DOS) attack&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The above techniques can be implemented on any ASP.NET website especially those who
use ASP.NET 2.0&amp;#39;s Membership and Profile provider.&lt;/p&gt;
&lt;p&gt;You can learn a lot more about performance and scalability improvement of ASP.NET and
ASP.NET AJAX websites from my book - 
&lt;a href="http://www.oreilly.com/catalog/9780596510503/"&gt;Building a Web 2.0 portal using
ASP.NET 3.5&lt;/a&gt;.&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1486901" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/performance/default.aspx">performance</category><category domain="http://msmvps.com/blogs/omar/archive/tags/asp.net/default.aspx">asp.net</category><category domain="http://msmvps.com/blogs/omar/archive/tags/production/default.aspx">production</category><category domain="http://msmvps.com/blogs/omar/archive/tags/ajax/default.aspx">ajax</category><category domain="http://msmvps.com/blogs/omar/archive/tags/.net/default.aspx">.net</category></item><item><title>My first book - Building a Web 2.0 Portal with ASP.NET 3.5</title><link>http://msmvps.com/blogs/omar/archive/2008/01/13/my-first-book-building-a-web-2-0-portal-with-asp-net-3-5.aspx</link><pubDate>Sun, 13 Jan 2008 20:23:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1461326</guid><dc:creator>omar</dc:creator><slash:comments>44</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/omar/rsscomments.aspx?PostID=1461326</wfw:commentRss><comments>http://msmvps.com/blogs/omar/archive/2008/01/13/my-first-book-building-a-web-2-0-portal-with-asp-net-3-5.aspx#comments</comments><description>&lt;p&gt;My first book &amp;quot;&lt;a href="http://www.oreilly.com/catalog/9780596510503/" target="_blank"&gt;Building a Web 2.0 Portal with ASP.NET 3.5&lt;/a&gt;&amp;quot; from O&amp;#39;Reilly is published and available in the stores. This book explains in detail the architecture design, development, test, deployment, performance and scalability challenges of my open source web portal &lt;a href="http://www.dropthings.com" target="_blank"&gt;Dropthings.com&lt;/a&gt;. Dropthings is a prototype of a web portal similar to &lt;a href="http://www.google.com/ig" target="_blank"&gt;iGoogle&lt;/a&gt; or &lt;a href="http://www.pageflakes.com" target="_blank"&gt;Pageflakes&lt;/a&gt;. But this portal is developed using recently released brand new technologies like ASP.NET 3.5, C# 3.0, Linq to Sql, Linq to XML, and Windows Workflow foundation. It makes heavy use of ASP.NET AJAX 1.0. Throughout my career I have built several state-of-the-art &lt;a href="http://omar.mvps.org" target="_blank"&gt;personal&lt;/a&gt;, educational, enterprise and &lt;a href="http://www.pageflakes.com" target="_blank"&gt;mass consumer web portals&lt;/a&gt;. This book collects my experience in building all of those portals.&lt;/p&gt;&lt;p&gt;O&amp;#39;Reilly Website:&lt;br /&gt;&lt;a href="http://www.oreilly.com/catalog/9780596510503/"&gt;http://www.oreilly.com/catalog/9780596510503/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Amazon:&lt;br /&gt;&lt;a href="http://www.amazon.com/Building-Web-2-0-Portal-ASP-NET/dp/0596510500"&gt;http://www.amazon.com/Building-Web-2-0-Portal-ASP-NET/dp/0596510500&lt;/a&gt;&lt;br /&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Disclaimer: This book does not show you how to build Pageflakes. Dropthings is entirely different in terms of architecture, implementation and the technologies involved.&lt;/p&gt; &lt;p&gt;You learn how to: &lt;/p&gt; &lt;ul&gt; &lt;li&gt;Implement a highly decoupled architecture following the popular n-tier, widget-based application model  &lt;/li&gt;&lt;li&gt;Provide drag-and-drop functionality, and use ASP.NET 3.5 to build the server-side part of the web layer  &lt;/li&gt;&lt;li&gt;Use LINQ to build the data access layer, and Windows Workflow Foundation to build the business layer as a collection of workflows  &lt;/li&gt;&lt;li&gt;Build client-side widgets using JavaScript for faster performance and better caching  &lt;/li&gt;&lt;li&gt;Get maximum performance out of the ASP.NET AJAX Framework for faster, more dynamic, and scalable sites  &lt;/li&gt;&lt;li&gt;Build a custom web service call handler to overcome shortcomings in ASP.NET AJAX 1.0 for asynchronous, transactional, cache-friendly web services  &lt;/li&gt;&lt;li&gt;Overcome JavaScript performance problems, and help the user interface load faster and be more responsive  &lt;/li&gt;&lt;li&gt;Solve various scalability and security problems as your site grows from hundreds to millions of users  &lt;/li&gt;&lt;li&gt;Deploy and run a high-volume production site while solving software, hardware, hosting, and Internet infrastructure problems &lt;/li&gt;&lt;/ul&gt;If you&amp;#39;re ready to build state-of-the art, high-volume web applications that can withstand millions of hits per day, this book has exactly what you need.&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1461326" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/sql+server/default.aspx">sql server</category><category domain="http://msmvps.com/blogs/omar/archive/tags/asp.net/default.aspx">asp.net</category><category domain="http://msmvps.com/blogs/omar/archive/tags/pageflakes/default.aspx">pageflakes</category><category domain="http://msmvps.com/blogs/omar/archive/tags/production/default.aspx">production</category><category domain="http://msmvps.com/blogs/omar/archive/tags/linq/default.aspx">linq</category><category domain="http://msmvps.com/blogs/omar/archive/tags/workflow/default.aspx">workflow</category><category domain="http://msmvps.com/blogs/omar/archive/tags/ajax/default.aspx">ajax</category><category domain="http://msmvps.com/blogs/omar/archive/tags/.net/default.aspx">.net</category><category domain="http://msmvps.com/blogs/omar/archive/tags/IIS/default.aspx">IIS</category></item><item><title>Linq to SQL: How to Attach object to a different data context</title><link>http://msmvps.com/blogs/omar/archive/2007/12/08/linq-to-sql-how-to-attach-object-to-a-different-data-context.aspx</link><pubDate>Sat, 08 Dec 2007 12:59:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1386679</guid><dc:creator>omar</dc:creator><slash:comments>15</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/omar/rsscomments.aspx?PostID=1386679</wfw:commentRss><comments>http://msmvps.com/blogs/omar/archive/2007/12/08/linq-to-sql-how-to-attach-object-to-a-different-data-context.aspx#comments</comments><description>&lt;p&gt;After upgrading to Visual Studio 2008 RTM, you will have trouble
updating Linq to SQL Classes which are read from one data context
and then updated into another data context. You will get this
exception during update:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;
&lt;u&gt;System.NotSupportedException: An attempt has been made to Attach
or Add an entity that is not new, perhaps having been loaded from
another DataContext.&amp;nbsp; This is not supported.
&lt;br /&gt;&lt;/u&gt;
&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Here&amp;#39;s a typical example taken from a 
&lt;a href="http://forums.microsoft.com/msdn/ShowPost.aspx?postid=2524396&amp;amp;siteid=1"&gt;
Forum post&lt;/a&gt;:&lt;/p&gt;
&lt;div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   1:&lt;/span&gt; public static void
UpdateEmployee(Employee employee)
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   2:&lt;/span&gt; {
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   3:&lt;/span&gt; using (HRDataContext dataContext =
new HRDataContext())
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   4:&lt;/span&gt; {
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   5:&lt;/span&gt; //Get original employee
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   6:&lt;/span&gt; Employee originalEmployee =
dataContext.Employees.Single(e=
&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;e.EmployeeId==employee.EmployeeId);
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   7:&lt;/span&gt;  
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   8:&lt;/span&gt; //attach to datacontext
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   9:&lt;/span&gt;
dataContext.Employees.Attach(employee, originalEmployee);
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  10:&lt;/span&gt;  
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  11:&lt;/span&gt; //save changes
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  12:&lt;/span&gt; dataContext.SubmitChanges();
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  13:&lt;/span&gt;  
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  14:&lt;/span&gt; }
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  15:&lt;/span&gt; }
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;When you call the Attach function, you will get the exception
mentioned above.&lt;/p&gt;
&lt;p&gt;Here&amp;#39;s a way to do this. First, create a partial class that adds
a 
&lt;u&gt;Detach&lt;/u&gt; method to 
&lt;u&gt;Employee&lt;/u&gt; class. This method will detach the object from it&amp;#39;s
data context and detach associated objects.&lt;/p&gt;
&lt;div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   1:&lt;/span&gt; public partial class Employee
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   2:&lt;/span&gt; {
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   3:&lt;/span&gt;   public void Detach()
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   4:&lt;/span&gt;   {
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   5:&lt;/span&gt;     this.PropertyChanged = null;
this.PropertyChanging = null;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   6:&lt;/span&gt;  
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   7:&lt;/span&gt;     // Assuming there&amp;#39;s a foreign
key from Employee to Boss
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   8:&lt;/span&gt;     this.Boss = default(EntityRef
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;
&lt;span class="html"&gt;Boss&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   9:&lt;/span&gt;     // Similarly set child objects
to default as well
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  10:&lt;/span&gt;  
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  11:&lt;/span&gt;     this.Subordinates =
default(EntitySet
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;
&lt;span class="html"&gt;Subordinate&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  12:&lt;/span&gt;   }
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  13:&lt;/span&gt; }
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  14:&lt;/span&gt;  
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  15:&lt;/span&gt;  
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Now during update, call 
&lt;u&gt;Detach&lt;/u&gt; before attaching the object to a 
&lt;u&gt;DataContext&lt;/u&gt;.&lt;/p&gt;
&lt;div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   1:&lt;/span&gt; public static void
UpdateEmployee(Employee employee)
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   2:&lt;/span&gt; {
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   3:&lt;/span&gt;     using (HRDataContext
dataContext = new HRDataContext())
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   4:&lt;/span&gt;     {
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   5:&lt;/span&gt;         //attach to datacontext
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   6:&lt;/span&gt;         employee.Detach();
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   7:&lt;/span&gt;  
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   8:&lt;/span&gt;        
dataContext.Employees.Attach(employee);
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   9:&lt;/span&gt;         //save changes
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  10:&lt;/span&gt;  
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  11:&lt;/span&gt;        
dataContext.SubmitChanges();
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  12:&lt;/span&gt;     }
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  13:&lt;/span&gt; }
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  14:&lt;/span&gt;  
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This&amp;#39;ll work. It assumes the employee object already has its
primary key populated.&lt;/p&gt;
&lt;p&gt;You might see during update, it&amp;#39;s generating a bloated UPDATE
statement where each and every property is appearing on the WHERE
clause. In that case, set 
&lt;u&gt;UpdateCheck&lt;/u&gt; to 
&lt;u&gt;Never&lt;/u&gt; for all properties of 
&lt;u&gt;Employee&lt;/u&gt; class from the Object Relational Designer.&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1386679" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/linq/default.aspx">linq</category><category domain="http://msmvps.com/blogs/omar/archive/tags/.net/default.aspx">.net</category></item><item><title>On-demand UI loading on AJAX websites</title><link>http://msmvps.com/blogs/omar/archive/2007/11/09/on-demand-ui-loading-on-ajax-websites.aspx</link><pubDate>Fri, 09 Nov 2007 09:01:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1289498</guid><dc:creator>omar</dc:creator><slash:comments>8</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/omar/rsscomments.aspx?PostID=1289498</wfw:commentRss><comments>http://msmvps.com/blogs/omar/archive/2007/11/09/on-demand-ui-loading-on-ajax-websites.aspx#comments</comments><description>&lt;p&gt;AJAX websites are all about loading as many features as possible
into the browser without having any postback. If you look at the
Start Pages like 
&lt;a href="http://www.pageflakes.com"&gt;Pageflakes&lt;/a&gt;, it&amp;#39;s only one
single page that gives you all the features of the whole
application with zero postback. A quick and dirty approach for
doing this is to deliver every possible html snippets inside hidden
divs during page load and then make those divs visible when needed.
But this makes first time loading way too long and browser gives
sluggish performance as too much stuff is on the DOM. So, a better
approach is to load html snippet and necessary javascript
on-demand. In my 
&lt;a href="http://www.dropthings.com"&gt;dropthings&lt;/a&gt; project, I have
shown an example how this is done.&lt;/p&gt;
&lt;p&gt;
&lt;img height="424" alt="clip_image002" src="http://omar.mvps.org/images/IncrementalUIloadingonAJAXwebsites_12E95/clip_image002.gif" width="480" /&gt;
&lt;/p&gt;
&lt;p&gt;When you click on the &amp;quot;help&amp;quot; link, it loads the content of the
help dynamically. This html is not delivered as part of the 
&lt;u&gt;default.aspx&lt;/u&gt; that renders the first page. Thus the giant
html and graphics related to the help section has no effect on site
load performance. It is only loaded when user clicks the &amp;quot;help&amp;quot;
link. Moreover, it gets cached on the browser and thus loads only
once. When user clicks the &amp;quot;help&amp;quot; link again, it&amp;#39;s served directly
from the browser cache, instead of fetching from the origin server
again.&lt;/p&gt;
&lt;p&gt;The principle is making an XMLHTTP call to an 
&lt;u&gt;.aspx&lt;/u&gt; page, get the response html, put that response html
inside a container DIV, make that DIV visible.&lt;/p&gt;
&lt;p&gt;AJAX framework has a 
&lt;u&gt;Sys.Net.WebRequest&lt;/u&gt; class which you can use to make regular
HTTP calls. You can define http method, URI, headers and the body
of the call. It&amp;rsquo;s kind of a low level function for making
direct calls via XMLHTTP. Once you construct a web request, you can
execute it using 
&lt;u&gt;Sys.Net.XMLHttpExecutor&lt;/u&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   1:&lt;/span&gt; function showHelp()
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   2:&lt;/span&gt; {
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   3:&lt;/span&gt;     var request = 
&lt;span class="kwrd"&gt;new&lt;/span&gt; Sys.Net.WebRequest();
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   4:&lt;/span&gt;     request.set_httpVerb(
&lt;span class="str"&gt;&amp;quot;GET&amp;quot;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   5:&lt;/span&gt;     request.set_url(
&lt;span class="str"&gt;&amp;#39;help.aspx&amp;#39;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   6:&lt;/span&gt;     request.add_completed(
function( executor )
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   7:&lt;/span&gt;     {
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   8:&lt;/span&gt;         
&lt;span class="kwrd"&gt;if&lt;/span&gt; (executor.get_responseAvailable()) 
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   9:&lt;/span&gt;         {
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  10:&lt;/span&gt;             var helpDiv = $get(
&lt;span class="str"&gt;&amp;#39;HelpDiv&amp;#39;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  11:&lt;/span&gt;             var helpLink = $get(
&lt;span class="str"&gt;&amp;#39;HelpLink&amp;#39;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  12:&lt;/span&gt;             
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  13:&lt;/span&gt;             var helpLinkBounds =
Sys.UI.DomElement.getBounds(helpLink);
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  14:&lt;/span&gt;             
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  15:&lt;/span&gt;             helpDiv.style.top =
(helpLinkBounds.y + helpLinkBounds.height) + 
&lt;span class="str"&gt;&amp;quot;px&amp;quot;&lt;/span&gt;;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  16:&lt;/span&gt;             
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  17:&lt;/span&gt;             var content =
executor.get_responseData();
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  18:&lt;/span&gt;             helpDiv.innerHTML =
content;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  19:&lt;/span&gt;             helpDiv.style.display =

&lt;span class="str"&gt;&amp;quot;block&amp;quot;&lt;/span&gt;;                       
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  20:&lt;/span&gt;         }
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  21:&lt;/span&gt;     });
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  22:&lt;/span&gt;     
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  23:&lt;/span&gt;     var executor = 
&lt;span class="kwrd"&gt;new&lt;/span&gt; Sys.Net.XMLHttpExecutor();
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  24:&lt;/span&gt;     request.set_executor(executor);

&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  25:&lt;/span&gt;     executor.executeRequest();
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  26:&lt;/span&gt; }
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The example shows how the help section is loaded by hitting 
&lt;u&gt;help.aspx&lt;/u&gt; and injecting its response inside the 
&lt;u&gt;HelpDiv&lt;/u&gt;. The response can be cached by the 
&lt;a&gt;output cache directive&lt;/a&gt; set on 
&lt;u&gt;help.aspx&lt;/u&gt;. So, next time when user clicks on the link, the
UI pops up immediately. The 
&lt;u&gt;help.aspx&lt;/u&gt; file has no 
&lt;u&gt;&amp;lt;html&amp;gt;&lt;/u&gt; block, only the content that is set inside the 
&lt;a&gt;DIV&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   1:&lt;/span&gt; 
&lt;span class="asp"&gt;&amp;lt;%@ Page Language=&amp;quot;C#&amp;quot; AutoEventWireup=&amp;quot;true&amp;quot;
CodeFile=&amp;quot;Help.aspx.cs&amp;quot; Inherits=&amp;quot;Help&amp;quot; %&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   2:&lt;/span&gt; 
&lt;span class="asp"&gt;&amp;lt;%@ OutputCache Location=&amp;quot;ServerAndClient&amp;quot;
Duration=&amp;quot;604800&amp;quot; VaryByParam=&amp;quot;none&amp;quot; %&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   3:&lt;/span&gt; 
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;
&lt;span class="html"&gt;div&lt;/span&gt; 
&lt;span class="attr"&gt;class&lt;/span&gt;
&lt;span class="kwrd"&gt;=&amp;quot;helpContent&amp;quot;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   4:&lt;/span&gt; 
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;
&lt;span class="html"&gt;div&lt;/span&gt; 
&lt;span class="attr"&gt;id&lt;/span&gt;
&lt;span class="kwrd"&gt;=&amp;quot;lipsum&amp;quot;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   5:&lt;/span&gt; 
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;
&lt;span class="html"&gt;p&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   6:&lt;/span&gt; Lorem ipsum dolor sit amet,
consectetuer adipiscing elit. Duis lorem
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   7:&lt;/span&gt; eros, volutpat sit amet, venenatis
vitae, condimentum at, dolor. Nunc
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   8:&lt;/span&gt; porttitor eleifend tellus. Praesent
vitae neque ut mi rutrum cursus.
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Using this approach, you can break the UI into smaller 
&lt;u&gt;.aspx&lt;/u&gt; files. Although these 
&lt;u&gt;.aspx&lt;/u&gt; files cannot have JavaScript or stylesheet blocks, but
they can contain large amount of html that you need to show on the
UI on-demand. Thus you can keep initial download to absolute
minimum just for loading the basic stuffs. When user explores new
features on the site, load those areas incrementally.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1289498" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/asp.net/default.aspx">asp.net</category><category domain="http://msmvps.com/blogs/omar/archive/tags/javascript/default.aspx">javascript</category><category domain="http://msmvps.com/blogs/omar/archive/tags/ajax/default.aspx">ajax</category><category domain="http://msmvps.com/blogs/omar/archive/tags/.net/default.aspx">.net</category></item><item><title>Safe COM: Managed Disposable Strongly Typed safe wrapper to late bound COM</title><link>http://msmvps.com/blogs/omar/archive/2007/10/27/safe-com-managed-disposable-strongly-typed-safe-wrapper-to-late-bound-com.aspx</link><pubDate>Sat, 27 Oct 2007 03:35:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1266083</guid><dc:creator>omar</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/omar/rsscomments.aspx?PostID=1266083</wfw:commentRss><comments>http://msmvps.com/blogs/omar/archive/2007/10/27/safe-com-managed-disposable-strongly-typed-safe-wrapper-to-late-bound-com.aspx#comments</comments><description>&lt;span id="intelliTXT"&gt;&lt;/span&gt;&lt;span id="intelliTXT"&gt;
&lt;p&gt;There are several problems using COM from .NET:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You cannot implement the Dispose pattern by utilizing the &amp;quot;&lt;code&gt;&lt;span class="cs-keyword"&gt;using&lt;/span&gt;&lt;/code&gt;&amp;quot; block in order to safely dispose COM references. &lt;/li&gt;
&lt;li&gt;You cannot guaranty COM references are finalized. There&amp;#39;s no way to implement &amp;quot;&lt;code&gt;~Destructor()&lt;/code&gt;&amp;quot; for COM references. &lt;/li&gt;
&lt;li&gt;COM reference is not released when a call to &lt;code&gt;Marshal.ReleaseComObject&lt;/code&gt; is skipped due to an &lt;code&gt;Exception&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;When you &amp;quot;Add Reference...&amp;quot; to a COM library, the reference is version specific. So, if you add a reference to the Office 2003 COM library, it does not work properly when deployed to Office 2000. &lt;/li&gt;
&lt;li&gt;The only solution to version independent COM is to use Late Bound operations but you miss all the features of a strongly typed language. &lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Let&amp;#39;s solve all these problems. We want to use a &lt;b&gt;Managed strongly typed&lt;/b&gt; approach to &lt;b&gt;Late Bound&lt;/b&gt; COM operations and also utilize the &lt;b&gt;Dispose pattern&lt;/b&gt; on COM objects. The solution proposed &lt;a class="" href="http://www.codeproject.com/csharp/safecomwrapper.asp"&gt;here&lt;/a&gt; works for any COM object which can be Microsoft Office COM libraries, IE &amp;amp; DHTML objects and even your own COM objects. You should use this approach whenever you are dealing with any type of COM library.&lt;/p&gt;
&lt;p&gt;If you like this solution, please vote for me.&lt;br /&gt;&lt;a href="http://www.codeproject.com/csharp/safecomwrapper.asp"&gt;http://www.codeproject.com/csharp/safecomwrapper.asp&lt;/a&gt;&lt;/p&gt;&lt;/span&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1266083" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/.net/default.aspx">.net</category><category domain="http://msmvps.com/blogs/omar/archive/tags/COM/default.aspx">COM</category></item><item><title>10 cool web development related articles in 2007</title><link>http://msmvps.com/blogs/omar/archive/2007/10/02/10-cool-web-development-related-articles-in-2007.aspx</link><pubDate>Tue, 02 Oct 2007 17:26:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1225686</guid><dc:creator>omar</dc:creator><slash:comments>8</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/omar/rsscomments.aspx?PostID=1225686</wfw:commentRss><comments>http://msmvps.com/blogs/omar/archive/2007/10/02/10-cool-web-development-related-articles-in-2007.aspx#comments</comments><description>&lt;p&gt;Here&amp;#39;s a list of 10 cool ASP.NET, AJAX and web development related articles and blog posts that I have written this year that you might want to take a look:&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.codeproject.com/install/13disasters.asp"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.codeproject.com/install/13disasters.asp"&gt;13 disasters for production website and their solutions&lt;/a&gt; &lt;br /&gt;Talks about 13 production disasters that can happen to any website any time and bring down your business.&amp;nbsp;&lt;/p&gt;&lt;a href="http://www.codeproject.com/Ajax/MakingGoogleIG.asp"&gt;Build Google IG like Ajax Start Page in 7 days using ASP.NET Ajax and .NET 3.0&lt;/a&gt; &lt;br /&gt;This block buster article shows how ASP.NET AJAX, Linq to XML, Linq to SQL and Workflow Foundation can be used to create a Google IG like start page in just 7 nights. Learn how to put together such hot technologies into one project and make a production site out of it.  &lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/archive/2007/04/29/serve-extensionless-url-from-asp-net-without-using-isapi-module-or-iis-6-wildcard-mapping.aspx"&gt;Serve extensionless URL from ASP.NET without using ISAPI module or IIS 6 Wildcard mapping&lt;/a&gt; &lt;br /&gt;Currently there are only two ways to service extentionless URL like &lt;a href="http://www.pageflakes.com/omar"&gt;www.pageflakes.com/omar&lt;/a&gt; that hits something besides the default document - use a custom ISAPI module or use IIS 6 wildcard mapping. Both has performance and scalability problems because both intercepts each and every hit. Learn how you can solve it by using a custom 404 handler.&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/archive/2007/09/19/request-format-is-unrecognized-for-url-unexpectedly-ending-in-somewebservicemethod.aspx"&gt;Request format is unrecognized for URL unexpectedly ending in /SomeWebServiceMethod&lt;/a&gt; &lt;br /&gt;Since ASP.NET AJAX 1.0 release, Microsoft prevented JSON hijacking by adding a special content type header. But this caused us some trouble. &lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/archive/2007/03/25/cleanup-inactive-anonymous-users-from-asp-net-membership-tables.aspx"&gt;Cleanup inactive anonymous users from ASP.NET Membership Tables&lt;/a&gt; &lt;br /&gt;When you store anonymous user profile using ASP.NET Membership provider and Anonymous Identification provider, you soon end up with lots of idle anonymous user data where those users never come back. We (Pageflakes) went through a lot of difficulty keeping our database size down as we allow anonymous users to do almost everything that a registered user can do. This introduces scalability challenge. See how we solved this problem.&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/archive/2007/03/24/prevent-denial-of-service-dos-attacks-in-your-web-application.aspx"&gt;Prevent Denial of Service (DOS) attacks in your web application&lt;/a&gt; &lt;br /&gt;Web applications can be brought down to its knees by hitting the site repeatedly or by calling expensive webservices randomly. Anyone can write a simple loop that hits a webserver very frequently from a high bandwidth connectivity and bring your production server down. See how to prevent such application level DOS attacks.&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/archive/2007/03/22/asp-net-ajax-extender-for-multi-column-widget-drag-drop.aspx"&gt;ASP.NET Ajax Extender for multi-column widget drag &amp;amp; drop&lt;/a&gt; &lt;br /&gt;It&amp;#39;s an ASP.NET AJAX extender that allows Pageflakes style drag &amp;amp; drop functionality between columns and rows. &lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/archive/2007/03/16/asp-net-ajax-in-depth-performance-analysis.aspx"&gt;ASP.NET Ajax in-depth performance analysis&lt;/a&gt; &lt;br /&gt;While building an open source start page using ASP.NET AJAX, I have done a lot of performance analysis on AJAX framework in order to improve first time load and perceived speed of javascript rich pages. Check out my analysis.&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/archive/2007/01/20/think-you-know-how-to-write-update-statement-think-again.aspx"&gt;Think you know how to write UPDATE statement? Think again.&lt;/a&gt; &lt;br /&gt;Learn how to optimize common UPDATE statements&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/archive/2007/01/07/make-a-surveillance-application-which-captures-desktop-and-emails-you-as-attachment.aspx"&gt;Make a surveillance application which captures desktop and then emails you as attachment&lt;/a&gt; &lt;br /&gt;Some time back I needed to capture a certain computers desktop in order to find out what that user is doing every day. So, I made a .NET 2.0 Winforms Application which stays on system tray (optional) and capture the desktop in given time interval (say every 60 secs) and emailed the captured images to me as message attachment (say every 30 mins).&lt;/p&gt; &lt;hr /&gt;  &lt;p&gt;Today I received MVP award for the 3rd time on Visual C#. Thanks to Microsoft for the award and setting up my &lt;a href="http://weblogs.asp.net/omarzabir"&gt;new blog&lt;/a&gt;. I will continue both my &lt;a href="http://msmvps.com/omar"&gt;MVPS Blog&lt;/a&gt; and this blog from now on.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1225686" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/asp.net/default.aspx">asp.net</category><category domain="http://msmvps.com/blogs/omar/archive/tags/production/default.aspx">production</category><category domain="http://msmvps.com/blogs/omar/archive/tags/javascript/default.aspx">javascript</category><category domain="http://msmvps.com/blogs/omar/archive/tags/ajax/default.aspx">ajax</category><category domain="http://msmvps.com/blogs/omar/archive/tags/.net/default.aspx">.net</category></item></channel></rss>