<?xml version="1.0"?>
<rss version="2.0">
<channel>
<title>Sharpening C</title>
<link>http://www.sharpeningc.com</link>
<description>A blog dedicated to c# and other IT technologies</description>
<language>en-us</language>
<managingEditor>editor@sharpeningc.com</managingEditor>
<item>
<title>asynchronous ASP.NET</title>
<link>http://www.sharpeningc.com/BlogPost.aspx?p=32</link>
<description><![CDATA[<p>
If an ASP.NET webpage is involved in intense I/O operations (e.g., intense database, file, or web service calls) and the webpage is heavily used, performance problems can occur if worker process threads are waiting for I/O threads to become available (see my last article for more information).&nbsp; In order to create scalable, efficient ASP.NET sites, asynchronous methods can be utilized to free up worker threads that would normally be frozen (and unusable) waiting for I/O threads to return.&nbsp; The simplest way to employ asynchronous code in your ASPX page is to use the AddOnPreRenderCompleteAsync method in the Page_Load page method.&nbsp; This method accepts two parameters, both delegates, which allow you to specify methods that will handle the beginning and end of the asynchronous operation you are trying to accomplish.&nbsp; To make this asynchronous method work, you must also make sure to add the <span class="attribute_code"><span style="font-size: 9pt; color: red; font-family: 'Courier New'">Async</span><span style="font-size: 9pt; color: blue; font-family: 'Courier New'">=&quot;true&quot;</span></span> page attribute to your web form&rsquo;s Page directive.<br />
<br />
This asynchronous code will fire between the PreRender and PreRenderComplete events of the page&rsquo;s event lifecycle.&nbsp; This means that the worker thread that was assigned to the HTTP request for this page will be put back in the thread pool right after the PreRender event has completed.&nbsp; When the asynchronous code has finished, a worker thread will be pulled from the worker thread pool and the page will continue along its event lifecycle.<br />
<br />
To see an example of this asynchronous model in action, you can go to MSDN (<a href="http://msdn2.microsoft.com/en-us/library/ba6dhx95(VS.80).aspx">http://msdn2.microsoft.com/en-us/library/ba6dhx95(VS.80).aspx</a>) or check out Jeff Prosise&rsquo;s webcast from TechEd 2007 (<a href="http://msevents.microsoft.com/cui/WebCastEventDetails.aspx?EventID=1032345482&amp;EventCategory=4&amp;culture=en-US&amp;CountryCode=US">http://msevents.microsoft.com/cui/WebCastEventDetails.aspx?EventID=1032345482&amp;EventCategory=4&amp;culture=en-US&amp;CountryCode=US</a>). 
</p>
]]></description>
<pubDate>Thu, 11 Oct 2007 17:45:18 GMT</pubDate>
<guid>http://www.sharpeningc.com/BlogPost.aspx?p=32</guid>
</item>
<item>
<title>IIS 6.0's use of http.sys</title>
<link>http://www.sharpeningc.com/BlogPost.aspx?p=31</link>
<description><![CDATA[<p>
In IIS 6.0, incoming client requests are handled by the kernel-mode HTTP.sys driver.&nbsp; Previous IIS versions used the user-mode Winsock driver, but IIS 6.0 enhances performance by using the kernel-mode HTTP.sys driver.&nbsp; Kernel-mode drivers are more efficient than user-mode drivers because they provide direct access to the internal system resources.&nbsp; On the other hand, user-mode drivers are less efficient but provide much better stability and security since they can only access the user address space.&nbsp; In IIS 6.0, the kernel-mode HTTP.sys driver enhances performance in the areas of request routing, request queuing, and request caching. 
</p>
<p>
<strong>HTTP.sys Routing and Queuing</strong> 
</p>
<p>
Higher performance is achieved when a request is passed directly between a kernel-mode process and a user-mode process than when a request is passed between two user-mode processes.&nbsp; HTTP.sys accomplishes this by playing a kernel-level proxy role between incoming client requests and user-mode worker processes.&nbsp; 
</p>
<p>
Worker processes are responsible for the actual processing of client requests.&nbsp; When you write an ASP.NET application, the application is hosted within a user-mode worker process (or processes if you are running a web garden).&nbsp; This worker process has a large pool of worker threads that can respond to HTTP.sys requests.&nbsp; If all the threads within the worker process&rsquo;s thread pool are in use, HTTP.sys&rsquo;s kernel-level queue will be utilized to temporarily hold requests until a thread becomes available.&nbsp; Heavy I/O activity is a common cause of worker thread pool depletion.&nbsp; To explain this situation it is important to understand that the worker process also has a pool of I/O threads that are used to accomplish I/O operations such as file, web service, or database access.&nbsp; Worker threads can get held up if they are waiting for I/O threads to finish processing heavy I/O operations.&nbsp; This lack of worker threads will cause request queuing by HTTP.sys to kick in.&nbsp; By the way, the HTTP.sys request queue can fill up making IIS respond back with 503 Server Not Available errors until threads become available once again. 
</p>
<p>
To put it all together, when a new client request comes in and there are no available worker threads, HTTP.sys places the request in its kernel-level request queue.&nbsp; This queue is tied to the application pool that is assigned to your ASP.NET application.&nbsp; When a worker thread becomes available within the application pool&#39;s worker process(es), it pulls the request from the request queue and processes it.&nbsp; When the worker process has completed processing the request, it utilizes HTTP.sys to respond back to the requesting client and returns the worker thread back into the thread pool. 
</p>
<p>
A noteworthy benefit of worker processes being user-mode rather than kernel-mode can be seen in how instability is handled.&nbsp; If an application hosted within a user-mode worker process crashes, requests are queued at the kernel level by HTTP.sys.&nbsp; The server simply hands out a new worker process, and the queued requests continue to be processed.&nbsp; Also, having worker processes run in user-mode protects the kernel from corruption and/or security violations that may be inherent to the ASP.NET application. 
</p>
<p>
<strong>HTTP.sys Caching</strong> 
</p>
<p>
Enhanced performance can also be seen in HTTP.sys&rsquo;s ability to cache request responses.&nbsp; This ability makes it possible for HTTP.sys to respond to requests directly and efficiently by not having to interact with the user-mode worker process when a particular request has already been handled and cached. 
</p>
<div style="text-align: center">
<img src="images/httpsys.jpg" alt="http.sys" width="437" height="400" /> 
</div>
]]></description>
<pubDate>Thu, 11 Oct 2007 17:45:18 GMT</pubDate>
<guid>http://www.sharpeningc.com/BlogPost.aspx?p=31</guid>
</item>
<item>
<title>asp.net page lifecycle events</title>
<link>http://www.sharpeningc.com/BlogPost.aspx?p=30</link>
<description><![CDATA[<p>
When writing asp.net code within a class that derives from System.Web.UI.Page (i.e., when creating a Web Form), it is important to understand the order in which the page&#39;s events fire. Being familiar with the page event lifecycle will allow you to make the best decision on when you can (and should) interact with page properties, controls, state, native resources, etc. 
</p>
<p>
During the page lifecycle, events (e.g., Init, PreRender, etc.) are fired that trigger certain built-in functionality to happen. Developers can interact with these events and add their own customizations. There are two common practices for interacting with these page lifecycle events: 
</p>
<ol>
	<li>Override the methods that raise these events. This is done by overriding the &ldquo;On&rdquo; methods (e.g., OnInit, OnPreRender, etc.) of the page. <br />
	</li>
	<li>Add event handlers to the page.&nbsp;These event handlers will be called when the page&#39;s lifecycle events fire. The first step to making this work is to ensure that the AutoEventWireup=&quot;true&quot; attribute exists in the @ Page directive. Next, simply use the Page_<em>eventname</em> syntax for each event that you want to intercept. You can see this in action with the default Page_Load method found on every newly created Web Form. So, the following two code examples would accomplish the same thing, with the second example requiring less typing: <br />
	<br />
	<div class="normal_code">
	<div class="comment_code">
	<span style="font-size: 8pt; color: blue; font-family: 'Courier New'">protected</span><span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000"> </font><span style="color: blue">override</span><font color="#000000"> </font><span style="color: blue">void</span><font color="#000000"> OnPreInit(</font><span style="color: #2b91af">EventArgs</span><font color="#000000"> e)</font></span> <br />
	<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000"><span></span>{</font></span> <br />
	<span style="font-size: 8pt; font-family: 'Courier New'"><span><font color="#000000"></font></span><span style="color: blue">&nbsp;&nbsp;&nbsp;&nbsp; this</span><font color="#000000">.PreInit += </font><span style="color: blue">new</span><font color="#000000"> </font><span style="color: #2b91af">EventHandler</span><font color="#000000">(_Default_PreInit);</font></span> <br />
	<span style="font-size: 8pt; font-family: 'Courier New'"><span><font color="#000000"></font></span><span style="color: blue">&nbsp;&nbsp;&nbsp;&nbsp; base</span><font color="#000000">.OnPreInit(e);</font></span> <br />
	<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000"><span></span>}</font></span> <br />
	<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000"></font></span><br />
	<span style="font-size: 8pt; font-family: 'Courier New'"><span><font color="#000000"></font></span><span style="color: blue">void</span><font color="#000000"> _Default_PreInit(</font><span style="color: blue">object</span><font color="#000000"> sender, </font><span style="color: #2b91af">EventArgs</span><font color="#000000"> e)</font></span> <br />
	<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000"><span></span>{</font></span> <br />
	<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000"></font>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#008000">//custom code here</font></span><br />
	<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000"><span></span>}</font></span> 
	</div>
	</div>
	<br />
	<div class="normal_code">
	<div class="comment_code">
	<span style="font-size: 8pt; font-family: 'Courier New'"><span><font color="#000000"></font></span><span style="color: blue">protected</span><font color="#000000"> </font><span style="color: blue">void</span><font color="#000000"> Page_PreInit(</font><span style="color: blue">object</span><font color="#000000"> sender, </font><span style="color: #2b91af">EventArgs</span><font color="#000000"> e)</font></span> <br />
	<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000"><span></span>{</font></span> <br />
	<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000"></font>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#008000">//custom code here</font></span><br />
	<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000"><span></span>}</font></span><span style="color: black"></span> 
	</div>
	</div>
	</li>
</ol>
<p>
Below I have listed the most common page events in the order they occur and some information on what is going on when a particular event fires. 
</p>
<p>
<strong><font size="2">PreInit</font></strong> <br />
When the PreInit event fires, personalization settings are initialized for the page. This is the appropriate time to dynamically change a page&rsquo;s theme or master page. 
</p>
<div class="normal_code">
<div class="comment_code">
<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#0000ff">base</font><font color="#000000">.MasterPageFile = </font><font color="#a31515">&quot;Main.master&quot;</font><font color="#000000">;</font></span> 
</div>
</div>
<br />
View state is not available yet. 
<p>
<font size="2"><strong>Init</strong> </font><br />
The Init event is responsible for setting up all declared server controls on the page. Because view state is not available yet, each control&rsquo;s state is set to its default value. There are no guarantees as to the order in which controls will be initialized. Therefore, declared server controls cannot talk to each other at this time. 
</p>
<p>
<strong><font size="2">InitComplete<br />
</font></strong>This event occurs once all controls have been initialized. At this point in the page lifecycle, you can access all declared server controls and dynamically created controls that were created in conjunction with the Init event. You will not be able to see any user inputted data since view state has not populated the controls yet. 
</p>
<p>
<strong><font size="2">PreLoad<br />
</font></strong>At this point, postback and view state data has been loaded for each control on the page. 
</p>
<p>
<strong><font size="2">Load<br />
</font></strong>This is the most well known event because Web Forms automatically create the Page_Load event handler for the Load event. At this point in the page lifecycle, all the controls on the page are loaded and setup with view state and postback data. This is a very common place for controls to be customized based on user input. Native resource calls (e.g., database access, file I/O, etc.) commonly reside in the Page_Load method as well. 
</p>
<p>
<strong><em><font size="2">Control Events</font><br />
</em></strong>After the page&rsquo;s load event has completed, any fired server control events are handled. For example, if a page has a Button control on it and a user presses the button, the event handler for the button press will occur at this point in the page lifecycle. 
</p>
<p>
<strong><font size="2">LoadComplete<br />
</font></strong>All controls have been setup and control events handled at this point. 
</p>
<p>
<strong><font size="2">PreRender<br />
</font></strong>PreRender occurs before the page&rsquo;s controls are converted to HTML markup and sent out to the requesting browser. During the PreRender event, any controls that have their DataSourceID property set will have their DataBind method called. As an example, if you have a GridView that is data-bound to an ObjectDataSource, this is the point in the page lifecycle that the GridView will actually be filled with the ObjectDataSource&rsquo;s SelectMethod data. 
</p>
<p>
<strong><font size="2">PreRenderComplete<br />
</font></strong>At this point, pre-rendering has completed and the page is just about to be turned into an IO stream and sent out to the requesting browser. Since all controls that have their DataSourceID property set have now been filled with data, you can use this method to customize these data-bound controls. For example, you could add a custom ListItem to a DropDownList that is data bound to an ObjectDataSource. 
</p>
<p>
<strong><font size="2">SaveStateComplete</font><br />
</strong>Right before this event is fired, all view state is saved for the page. If you try and make any changes to the page or its controls, they will be discarded. 
</p>
<p>
<strong><font size="2">Unload</font><br />
</strong>At this late stage in the page lifecycle, the page is about to be unloaded from memory. This is a good time to do final clean-up operations like closing database connections or closing open files. This is also a great time to post log entries. The response stream is now closed, so you should not try to make calls into Response or you will get an exception. 
</p>
]]></description>
<pubDate>Thu, 11 Oct 2007 17:45:18 GMT</pubDate>
<guid>http://www.sharpeningc.com/BlogPost.aspx?p=30</guid>
</item>
<item>
<title>efficient paging via ObjectDataSource paging</title>
<link>http://www.sharpeningc.com/BlogPost.aspx?p=27</link>
<description><![CDATA[<p>
When using paging with data-bound controls, performance issues can arise when accessing large amounts of data.&nbsp; By default, all rows needed for the data-bound control will be acquired even if paging is only exposing a small subset of these rows per page index.&nbsp; Utilizing an ObjectDataSource (ODS) and enabling paging functionality within the ODS allows a specified amount of rows to be accessed from the database per page index.&nbsp; Setting the ODS to use paging requires a few extra properties to be utilized within the ODS: EnablingPaging, MaximumRowsParameterName, StartRowIndexParameterName, and SelectCountMethod to be specific. 
</p>
<p>
In this example, I am utilizing the following ODS: 
</p>
<div class="normal_code">
<div class="margin">
<p>
<span style="font-size: 8pt; color: blue; font-family: 'Courier New'">&lt;</span><span style="font-size: 8pt; color: #a31515; font-family: 'Courier New'">asp</span><span style="font-size: 8pt; color: blue; font-family: 'Courier New'">:</span><span style="font-size: 8pt; color: #a31515; font-family: 'Courier New'">ObjectDataSource</span><span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000"> </font><span style="color: red">ID</span><span style="color: blue">=&quot;ObjectDataSource1&quot;</span><font color="#000000"> </font><span style="color: red">runat</span><span style="color: blue">=&quot;server&quot;</span><font color="#000000"> </font><span style="color: red">EnablePaging</span><span style="color: blue">=&quot;True&quot;</span><font color="#000000"> </font><span style="color: red">SelectCountMethod</span><span style="color: blue">=&quot;GetDepartmentCount&quot; </span><span style="color: red">SelectMethod</span><span style="color: blue">=&quot;GetDepartments&quot;</span><font color="#000000"> </font><span style="color: red">TypeName</span><span style="color: blue">=&quot;TempBLL&quot;</span><font color="#000000"> </font><span style="color: red">MaximumRowsParameterName</span><span style="color: blue">=&quot;maximumRows&quot;</span><font color="#000000"> </font><span style="color: red">StartRowIndexParameterName</span><span style="color: blue">=&quot;startRowIndex&quot;&gt;</span></span> 
</p>
</div>
</div>
<p>
The ODS points to the following class: 
</p>
<div class="normal_code">
<div class="margin">
<span style="font-size: 8pt; color: blue; font-family: 'Courier New'">using</span><span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000"> System;</font></span> <br />
<span style="font-size: 8pt; color: blue; font-family: 'Courier New'">using</span><span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000"> System.Data;</font></span> <br />
<span style="font-size: 8pt; color: blue; font-family: 'Courier New'">using</span><span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000"> System.Configuration;</font></span> <br />
<span style="font-size: 8pt; color: blue; font-family: 'Courier New'">using</span><span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000"> System.Web;</font></span> <br />
<span style="font-size: 8pt; color: blue; font-family: 'Courier New'">using</span><span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000"> System.Web.Security;</font></span> <br />
<span style="font-size: 8pt; color: blue; font-family: 'Courier New'">using</span><span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000"> System.Web.UI;</font></span> <br />
<span style="font-size: 8pt; color: blue; font-family: 'Courier New'">using</span><span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000"> System.Web.UI.WebControls;</font></span> <br />
<span style="font-size: 8pt; color: blue; font-family: 'Courier New'">using</span><span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000"> System.Web.UI.WebControls.WebParts;</font></span> <br />
<span style="font-size: 8pt; color: blue; font-family: 'Courier New'">using</span><span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000"> System.Web.UI.HtmlControls;</font></span> <br />
<span style="font-size: 8pt; color: blue; font-family: 'Courier New'">using</span><span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000"> System.Data.SqlClient;</font></span> <br />
<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000"></font></span><br />
<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000">[System.ComponentModel.</font><span style="color: #2b91af">DataObject</span><font color="#000000">]</font></span> <br />
<span style="font-size: 8pt; color: blue; font-family: 'Courier New'">public</span><span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000"> </font><span style="color: blue">class</span><font color="#000000"> </font><span style="color: #2b91af">TempBLL</span></span> <br />
<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000">{</font></span> <br />
<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000">&nbsp;&nbsp;&nbsp; [System.ComponentModel.</font><span style="color: #2b91af">DataObjectMethod</span><font color="#000000">(System.ComponentModel.</font><span style="color: #2b91af">DataObjectMethodType</span><font color="#000000">.Select,<br />
&nbsp;&nbsp; &nbsp;</font><span style="color: blue">true</span><font color="#000000">)]</font></span> <br />
<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000">&nbsp;&nbsp;&nbsp; </font><span style="color: blue">public</span><font color="#000000"> </font><span style="color: #2b91af">DataTable</span><font color="#000000"> GetDepartments(</font><span style="color: blue">int</span><font color="#000000"> startRowIndex, </font><span style="color: blue">int</span><font color="#000000"> maximumRows)</font></span> <br />
<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000">&nbsp;&nbsp;&nbsp; {</font></span> <br />
<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><span style="color: blue">using</span><font color="#000000"> (</font><span style="color: #2b91af">SqlConnection</span><font color="#000000"> connection = </font><span style="color: blue">new</span><font color="#000000"> </font><span style="color: #2b91af">SqlConnection</span><font color="#000000">(</font><span style="color: #a31515">&quot;Data Source=localhost;Initial <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Catalog=AdventureWorks;Trusted_Connection=Yes&quot;</span><font color="#000000">))</font></span> <br />
<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</font></span> <br />
<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><span style="color: #2b91af">SqlCommand</span><font color="#000000"> command = connection.CreateCommand();</font></span> <br />
<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; command.CommandType = </font><span style="color: #2b91af">CommandType</span><font color="#000000">.StoredProcedure;</font></span> <br />
<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; command.CommandText = </font><span style="color: #a31515">&quot;HumanResources.uspGetDepartments&quot;</span><font color="#000000">;</font></span> <br />
<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; command.Parameters.Add(</font><span style="color: blue">new</span><font color="#000000"> </font><span style="color: #2b91af">SqlParameter</span><font color="#000000">(</font><span style="color: #a31515">&quot;@FirstRow&quot;</span><font color="#000000">, </font><span style="color: #2b91af">SqlDbType</span><font color="#000000">.Int));</font></span> <br />
<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; command.Parameters[</font><span style="color: #a31515">&quot;@FirstRow&quot;</span><font color="#000000">].Value = startRowIndex + 1;</font></span> <br />
<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; command.Parameters.Add(</font><span style="color: blue">new</span><font color="#000000"> </font><span style="color: #2b91af">SqlParameter</span><font color="#000000">(</font><span style="color: #a31515">&quot;@MaxRows&quot;</span><font color="#000000">, </font><span style="color: #2b91af">SqlDbType</span><font color="#000000">.Int));</font></span> <br />
<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; command.Parameters[</font><span style="color: #a31515">&quot;@MaxRows&quot;</span><font color="#000000">].Value = maximumRows;</font></span> <br />
<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><span style="color: #2b91af">DataSet</span><font color="#000000"> result = </font><span style="color: blue">new</span><font color="#000000"> </font><span style="color: #2b91af">DataSet</span><font color="#000000">();</font></span> <br />
<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><span style="color: #2b91af">SqlDataAdapter</span><font color="#000000"> adapter = </font><span style="color: blue">new</span><font color="#000000"> </font><span style="color: #2b91af">SqlDataAdapter</span><font color="#000000">(command);</font></span> <br />
<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; adapter.Fill(result);</font></span> <br />
<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000"></font></span><br />
<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><span style="color: #2b91af">HttpContext</span><font color="#000000">.Current.Items[</font><span style="color: #a31515">&quot;DepartmentRowCount&quot;</span><font color="#000000">] = (</font><span style="color: blue">int</span><font color="#000000">)result.Tables[1].Rows[0][0];</font></span> <br />
<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><span style="color: blue">return</span><font color="#000000"> result.Tables[0];</font></span> <br />
<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</font></span> <br />
<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000">&nbsp;&nbsp;&nbsp; }</font></span> <br />
<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000"></font></span><br />
<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000">&nbsp;&nbsp;&nbsp; </font><span style="color: blue">public</span><font color="#000000"> </font><span style="color: blue">int</span><font color="#000000"> GetDepartmentCount()</font></span> <br />
<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000">&nbsp;&nbsp;&nbsp; {</font></span> <br />
<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><span style="color: blue">return</span><font color="#000000"> (</font><span style="color: blue">int</span><font color="#000000">)</font><span style="color: #2b91af">HttpContext</span><font color="#000000">.Current.Items[</font><span style="color: #a31515">&quot;DepartmentRowCount&quot;</span><font color="#000000">];</font></span> <br />
<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000">&nbsp;&nbsp;&nbsp; }</font></span> <br />
<span style="font-size: 8pt; font-family: 'Courier New'"><font color="#000000">}</font></span> <br />
</div>
</div>
<p>
When using paging within the ODS, the method specified in the SelectMethod property must, at the least, have a parameter to indicate the starting row index and a parameter to indicate how many rows should be returned per page.&nbsp; The names of these parameters are set in the StartRowIndexParameterName and MaximumRowsParameterName properties of the ODS respectively. 
</p>
<p>
The purpose of the customized SelectMethod is to provide a mechanism by which only a pre-determined number of rows will be returned from the database per page index.&nbsp; The ODS will take care of passing in the appropriate arguments for the two custom parameters.&nbsp; The &ldquo;maximumRows&rdquo; parameter is determined from the data-bound control&rsquo;s PageSize property and the &ldquo;startRowIndex&rdquo; parameter automatically increases based on the currently selected page index.&nbsp; For example, if you only want 5 rows to show up per page on a GridView, simply set the GridView&rsquo;s PageSize property to 5 and the ODS will automatically send the value 5 into the SelectMethod&rsquo;s parameter that is named in the MaximumRowsParameterName property.&nbsp; This value can then be used to limit the amount of rows being grabbed from the database (as I did with the uspGetDepartments stored procedure). 
</p>
<p>
The SelectCountMethod property points to the second method within TempBLL.cs.&nbsp; This method lets the data-bound control know the total amount of rows so it can display the correct number of page links.&nbsp; This is necessary because the paging enabled ODS will only be returning a subset of the total rows.&nbsp; I am utilizing the HttpContext in order to prevent two round-trips to the database since the SelectCountMethod is called after the SelectMethod.&nbsp; I originally got the HttpContext idea from Fritz Onion. 
</p>
<p>
I am using SQL Server 2005 in this example, so I am able to use the ROW_NUMBER() function in my T-SQL to grab the appropriate group of rows per page index: 
</p>
<div class="normal_code">
<div class="margin">
<font size="2"><span style="color: blue; font-family: 'Courier New'">CREATE</span><span style="font-family: 'Courier New'"><font color="#000000"> </font><span style="color: blue">PROCEDURE</span><font color="#000000"> [HumanResources]</font><span style="color: gray">.</span><font color="#000000">[uspGetDepartments]</font></span></font> <br />
<span style="font-family: 'Courier New'"><font size="2"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @FirstRow </font><span style="color: blue">int</span><span style="color: gray">,</span></font></span> <br />
<span style="font-family: 'Courier New'"><font size="2"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @MaxRows </font><span style="color: blue">int</span></font></span> <br />
<span style="color: blue; font-family: 'Courier New'"><font size="2">AS</font></span> <br />
<span style="color: blue; font-family: 'Courier New'"><font size="2">BEGIN</font></span> <br />
<span style="font-family: 'Courier New'"><font size="2"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><span style="color: blue">WITH</span><font color="#000000"> </font><font color="#000000">OrderedDepartments </font><span style="color: blue">AS</span><span style="color: blue"></span></font></span> <br />
<span style="font-family: 'Courier New'"><font size="2"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><span style="color: gray">(</span></font></span> <br />
<span style="font-family: 'Courier New'"><font size="2"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><span style="color: blue">SELECT</span><font color="#000000"> d</font><span style="color: gray">.</span><font color="#000000">DepartmentID</font><span style="color: gray">,</span><font color="#000000"> d</font><span style="color: gray">.</span><font color="#000000">[Name]</font><span style="color: gray">,</span><font color="#000000"> ROW_NUMBER</font><span style="color: gray">()</span><font color="#000000"> </font><span style="color: blue">OVER</span><font color="#000000"> </font><span style="color: gray">(</span><span style="color: blue">ORDER</span><font color="#000000"> </font><span style="color: blue">BY</span><font color="#000000"> d</font><span style="color: gray">.</span><font color="#000000">[Name]</font><span style="color: gray">)</span><font color="#000000"> </font><span style="color: blue">AS <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: red">&#39;RowNumber&#39;</span></font></span> <br />
<span style="font-family: 'Courier New'"><font size="2"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><span style="color: blue">FROM</span><font color="#000000"> HumanResources</font><span style="color: gray">.</span><font color="#000000">Department d</font></font></span> <br />
<span style="font-family: 'Courier New'"><font size="2"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><span style="color: gray">)</span></font></span> <br />
<span style="font-family: 'Courier New'"><font size="2"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><span style="color: blue">SELECT</span><font color="#000000"> od</font><span style="color: gray">.</span><font color="#000000">DepartmentID</font><span style="color: gray">,</span><font color="#000000"> od</font><span style="color: gray">.</span><font color="#000000">[Name]</font></font></span> <br />
<span style="font-family: 'Courier New'"><font size="2"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><span style="color: blue">FROM</span><font color="#000000"> OrderedDepartments od</font></font></span> <br />
<span style="font-family: 'Courier New'"><font size="2"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><span style="color: blue">WHERE</span><font color="#000000"> RowNumber </font><span style="color: gray">BETWEEN</span><font color="#000000"> @FirstRow </font><span style="color: gray">AND</span><font color="#000000"> </font><span style="color: gray">(</span><font color="#000000">@FirstRow </font><span style="color: gray">+</span><font color="#000000"> @MaxRows) </font><span style="color: gray">-</span><font color="#000000"> 1</font></font></span>&nbsp;<br />
<span style="color: gray; font-family: 'Courier New'"><font size="2"></font></span><br />
<span style="font-family: 'Courier New'"><font size="2"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><span style="color: blue">SELECT</span><font color="#000000"> </font><span style="color: fuchsia">COUNT</span><span style="color: gray">(*)</span><font color="#000000"> </font><span style="color: blue">FROM</span><font color="#000000"> HumanResources</font><span style="color: gray">.</span><font color="#000000">Department</font></font></span> <br />
<span style="color: blue; font-family: 'Courier New'"><font size="2">END</font></span> <br />
</div>
</div>
<p>
With this stored procedure, I am able to get the proper subset of rows and the total row count.&nbsp; The multiple result sets are placed within distinct tables when the stored procedure is called in the SelectMethod.&nbsp; This allows the SelectMethod to grab the subset of rows needed for the current page index and retrieve the total row count in one database call. 
</p>
]]></description>
<pubDate>Thu, 11 Oct 2007 17:45:18 GMT</pubDate>
<guid>http://www.sharpeningc.com/BlogPost.aspx?p=27</guid>
</item>
<item>
<title>deleting or moving dynamically created controls</title>
<link>http://www.sharpeningc.com/BlogPost.aspx?p=12</link>
<description><![CDATA[<p>
When adding controls dynamically to a page, it is important to do so on every page load or they no longer exist.&nbsp; For example, the code below reads contact records from a database and creates LinkButtons for each contact.&nbsp; It also encodes the LinkButtons with a CommandArgument set to the contact&#39;s unique identifier and wires it up to an event handler before adding to the page via a panel. 
</p>
<div class="normal_code">
<div class="margin">
<span class="keyword_code">protected override void</span> OnInit(<span class="object_code">EventArgs</span> e)<br />
{<br />
&nbsp;&nbsp;&nbsp; SetupContacts();<br />
} <br />
<br />
<span class="keyword_code">private void</span> SetupContacts()<br />
{<br />
&nbsp;&nbsp;&nbsp; .<br />
&nbsp;&nbsp;&nbsp; .<br />
&nbsp;&nbsp;&nbsp; .<br />
&nbsp;&nbsp;&nbsp; <span class="keyword_code">foreach</span> (<span class="object_code">ContactsRow</span> row <span class="keyword_code">in</span> contactsTable.Rows)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="object_code">LinkButton</span> link = <span class="keyword_code">new</span> <span class="object_code">LinkButton</span>();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; link.Text = row.FirstName + <span class="string_code">&quot; &quot;</span> + row.LastName;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; link.CommandArgument = row.ContactID.ToString();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; link.Click += <span class="keyword_code">new</span> <span class="object_code">EventHandler</span>(link_Click);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;panel1.Controls.Add(link);<br />
} 
</div>
</div>
<p>
A problem can occur when one of the dynamically created controls is deleted or moved on the page.&nbsp; This is due to the fact that ViewState connects its information to a control by the control&rsquo;s ID.&nbsp; If you do not specify an ID, .Net creates the ID dynamically (e.g., ctl14, ctl19, etc.).&nbsp; This will cause issues if you create a control on your page that deletes or moves the dynamically created control(s).&nbsp; This is because it will change the ID of the control(s) after ViewState has been loaded and connected to the previous ID(s).&nbsp; This is caused because child controls have their events fire after the ViewState is loaded for the page and tied to each controls&rsquo; ID.&nbsp; To illustrate, suppose we have a Button control that accomplishes the following: 
</p>
<div class="normal_code">
<div class="margin">
<span class="keyword_code">protected void</span> Delete_Click(<span class="object_code">object</span> sender, <span class="object_code">EventArgs</span> e)<br />
{<br />
&nbsp;&nbsp;&nbsp; <span class="comment_code">//delete contact with unique identifier of 1</span><br />
&nbsp;&nbsp;&nbsp; DeleteContact(1);<br />
&nbsp;&nbsp;&nbsp; <span class="comment_code">//refresh custom controls to eliminate deleted contact<br />
</span>&nbsp;&nbsp;&nbsp; SetupControls();<br />
} 
</div>
</div>
<p>
After clicking the Delete button, the deleted contact will disappear but none of the LinkButtons will fire properly on the next click.&nbsp; They will begin to work after you click one of the LinkButtons once, because the corresponding postback will reconnect the LinkButtons&rsquo; IDs to the ViewState successfully.&nbsp; The key to getting around this issue is to be sure to add a unique identifier when you dynamically create the controls.&nbsp; This will keep the ViewState info connected to the controls even if some of them are moved or deleted.&nbsp; See the bolded code in the modified SetupContacts code below. 
</p>
<div class="normal_code">
<div class="margin">
<span class="keyword_code">private void</span> SetupContacts()<br />
{<br />
&nbsp;&nbsp;&nbsp; <span class="keyword_code">foreach</span> (<span class="object_code">ContactsRow</span> row <span class="keyword_code">in</span> contactsTable.Rows)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="object_code">LinkButton</span> link = <span class="keyword_code">new</span> <span class="object_code">LinkButton</span>();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; link.Text = row.FirstName + <span class="string_code">&quot; &quot;</span> + row.LastName;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; link.CommandArgument = row.ContactID.ToString();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;link.Click += <span class="keyword_code">new</span> <span class="object_code">EventHandler</span>(link_Click);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; link.ID = <span class="string_code">&quot;contactLink&quot;</span> + row.ContactID.ToString();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; panel1.Controls.Add(link);<br />
&nbsp;&nbsp;&nbsp; }<br />
} 
</div>
</div>
]]></description>
<pubDate>Thu, 11 Oct 2007 17:45:18 GMT</pubDate>
<guid>http://www.sharpeningc.com/BlogPost.aspx?p=12</guid>
</item>
</channel>
</rss>
