<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/rss2full.xsl" type="text/xsl" media="screen"?><?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/itemcontent.css" type="text/css" media="screen"?><rss xmlns:blogChannel="http://backend.userland.com/blogChannelModule" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">
  <channel>
    <title>dotNetProfessional</title>
    <description>Garry McGlennon</description>
    <link>http://dotnetprofessional.com/blog/</link>
    <docs>http://www.rssboard.org/rss-specification</docs>
    <generator>BlogEngine.Net Syndication Generator 1.0.0.0 (http://dotnetblogengine.net/)</generator>
    <language>en-AU</language>
    <blogChannel:blogRoll>http://dotnetprofessional.com/blog/opml.axd</blogChannel:blogRoll>
    <dc:creator>Garry McGlennon</dc:creator>
    <dc:title>dotNetProfessional</dc:title>
    <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/Dotnetprofessional" type="application/rss+xml" /><item>
      <title>Turn multiple rows into a single string in SQL Server</title>
      <description>&lt;p&gt;I recently had the task of creating a report where they wanted one of the columns to list out all the users associated with a given report line item in a single comma separated string. My initial thoughts were, that this would involve some type of cursor or at least a loop of some description, which I'd then have to attach to the main result set. However, it seems there's a very nice little trick you can use that will solve this issue without the use of cursors or loops!&lt;/p&gt; &lt;p&gt;With the use of the COALESCE keyword you can create a list in a single line of SQL (except for declarations). I'll use the AdventureWorks database to demonstrate the technique. Assume&amp;nbsp; you need to get a list of Countries and the regions they contain, in a report similar to the one below: &lt;/p&gt; &lt;p&gt;&lt;a href="http://www.dotnetprofessional.com/blog/image.axd?picture=WindowsLiveWriter/TurnmultiplerowsintoasinglestringinSQLSe_13964/SampleReport_2.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="366" alt="Sample Report" src="http://www.dotnetprofessional.com/blog/image.axd?picture=WindowsLiveWriter/TurnmultiplerowsintoasinglestringinSQLSe_13964/SampleReport_thumb.jpg" width="484" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;To produce a list you can use the following SQL:&lt;/p&gt; &lt;div class="csharpcode-wrapper"&gt; &lt;div class="csharpcode"&gt;&lt;pre class="alt"&gt;&lt;span class="kwrd"&gt;DECLARE&lt;/span&gt; @&lt;span class="kwrd"&gt;result&lt;/span&gt; &lt;span class="kwrd"&gt;varchar&lt;/span&gt;(&lt;span class="kwrd"&gt;max&lt;/span&gt;)&lt;/pre&gt;&lt;pre class="alteven"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="kwrd"&gt;SELECT&lt;/span&gt;    @&lt;span class="kwrd"&gt;result&lt;/span&gt; = &lt;span class="kwrd"&gt;coalesce&lt;/span&gt;(@&lt;span class="kwrd"&gt;result&lt;/span&gt; + &lt;span class="str"&gt;', '&lt;/span&gt;, &lt;span class="str"&gt;''&lt;/span&gt;) + Name&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="kwrd"&gt;FROM&lt;/span&gt;    Person.StateProvince&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="kwrd"&gt;WHERE&lt;/span&gt;    Person.StateProvince.CountryRegionCode = @CountryRegionCode&lt;/pre&gt;&lt;pre class="alteven"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="kwrd"&gt;RETURN&lt;/span&gt; @&lt;span class="kwrd"&gt;Result&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="CopyToClipboard" style=""&gt;&lt;div&gt;&lt;a href="javascript:void(0);" onclick="CopyToClipboard_ViewPlain(copyToClipboardc2e8c1f0f660465b8e6cb3f6679e9c44_1328);"&gt;View Plain&lt;/a&gt; | &lt;a href="javascript:void(0);" onclick="CopyToClipboard_Copy(copyToClipboardc2e8c1f0f660465b8e6cb3f6679e9c44_1328);"&gt;Copy To Clipboard&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;
				&lt;div id="CopyToClipboard_Hidden" style="display:none;"&gt;&lt;/div&gt;
				&lt;div id="CopyToClipboard_FlashContainer"&gt;&lt;/div&gt;
                &lt;script type="text/javascript"&gt;

					function CopyToClipboard_Strip( text ){
						text = text.replace( /&amp;nbsp;/g, ' ' );
						text = text.replace( /&amp;quot;/g, '"' );
						text = text.replace( /&amp;#39;/g, '"' );
						text = text.replace( /&amp;amp;/g, '&amp;' );
						text = text.replace( /&amp;lt;/g, String.fromCharCode(60) );
						text = text.replace( /&amp;gt;/g, String.fromCharCode(62) );
						return text;
					}

                    function CopyToClipboard_Copy( text ){

						//### get reference to utility div
						var ele = document.getElementById('CopyToClipboard_Hidden');

						//### the following taken from: http://webchicanery.com/2006/11/14/clipboard-copy-javascript/
						if (false &amp;&amp; window.clipboardData) {
							window.clipboardData.setData( "Text", text );
						} else {
							document.getElementById('CopyToClipboard_FlashContainer').innerHTML = '';
							var divinfo = '&lt;embed id="CopyToClipboard_FlashFile" src="/blog/Extensions/_clipboard.swf" FlashVars="clipboard=' + encodeURIComponent(text) + '" width="0" height="0" type="application/x-shockwave-flash"&gt;&lt;/embed&gt;';
							document.getElementById('CopyToClipboard_FlashContainer').innerHTML = divinfo;
						}

                    }

					function CopyToClipboard_ViewPlain( text ){
						var win = window.open( '', 'CopyToClipboard_Window', 'width=480, height=480, toolbar=no, menubar=no, scrollbars=auto, resizable=yes, location=no, directories=no, status=no' );
						win.document.write( '&lt;html&gt;&lt;head&gt;&lt;title&gt;Code&lt;/title&gt;&lt;body style="margin:0;padding:0;"&gt;&lt;textarea style="width:100%;height:100%;border:0;"&gt;' + text + '&lt;/textarea&gt;&lt;/body&gt;&lt;/html&gt;' );
					}

                &lt;/script&gt;
            
					&lt;script type="text/javascript"&gt;
						var copyToClipboardc2e8c1f0f660465b8e6cb3f6679e9c44_1328 = CopyToClipboard_Strip('DECLARE @result varchar(max) SELECT    @result = coalesce(@result + \', \', \'\') + NameFROM    Person.StateProvinceWHERE    Person.StateProvince.CountryRegionCode = @CountryRegionCode RETURN @Result');
					&lt;/script&gt;
&lt;p&gt;The way this works is the COALESCE function returns the first non-null expression. For the first record this would be the empty string + Name as @Result would be null. However, the interesting thing is that because we keep concatinating to @Result a single value is returned from the whole result set. The only issue is that for this to work we need a variable to keep storing the information in. So if you want to apply this against another table that supplies the filter, you'll have to create a function that returns the string. As this is a scalar function (ie doesn't return a result set) its use within another query is extremely easy. Assuming a function for the above is called dbo.fnRegionsToString we are left with:&lt;/p&gt;
&lt;div class="csharpcode-wrapper"&gt;
&lt;div class="csharpcode"&gt;&lt;pre class="alt"&gt;&lt;span class="kwrd"&gt;SELECT&lt;/span&gt; Name &lt;span class="kwrd"&gt;AS&lt;/span&gt; Country, dbo.fnRegionsToString(CountryRegionCode) States&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="kwrd"&gt;FROM&lt;/span&gt;
         Person.CountryRegion&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="CopyToClipboard" style=""&gt;&lt;div&gt;&lt;a href="javascript:void(0);" onclick="CopyToClipboard_ViewPlain(copyToClipboardc2e8c1f0f660465b8e6cb3f6679e9c44_5393);"&gt;View Plain&lt;/a&gt; | &lt;a href="javascript:void(0);" onclick="CopyToClipboard_Copy(copyToClipboardc2e8c1f0f660465b8e6cb3f6679e9c44_5393);"&gt;Copy To Clipboard&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;
					&lt;script type="text/javascript"&gt;
						var copyToClipboardc2e8c1f0f660465b8e6cb3f6679e9c44_5393 = CopyToClipboard_Strip('SELECT Name AS Country, dbo.fnRegionsToString(CountryRegionCode) StatesFROM\r\n         Person.CountryRegion');
					&lt;/script&gt;
&lt;p&gt;The whole script which you can test against the AdventureWorks database is:&lt;/p&gt;
&lt;div class="csharpcode-wrapper"&gt;
&lt;div class="csharpcode"&gt;&lt;pre class="alt"&gt;&lt;span class="kwrd"&gt;IF&lt;/span&gt;  &lt;span class="kwrd"&gt;EXISTS&lt;/span&gt; (&lt;span class="kwrd"&gt;SELECT&lt;/span&gt; * &lt;span class="kwrd"&gt;FROM&lt;/span&gt; dbo.sysobjects &lt;span class="kwrd"&gt;WHERE&lt;/span&gt; [id] = OBJECT_ID(N&lt;span class="str"&gt;'[dbo].[fnRegionsToString]'&lt;/span&gt;) &lt;span class="kwrd"&gt;AND&lt;/span&gt; type &lt;span class="kwrd"&gt;in&lt;/span&gt; (N&lt;span class="str"&gt;'FN'&lt;/span&gt;, N&lt;span class="str"&gt;'IF'&lt;/span&gt;, N&lt;span class="str"&gt;'TF'&lt;/span&gt;, N&lt;span class="str"&gt;'FS'&lt;/span&gt;, N&lt;span class="str"&gt;'FT'&lt;/span&gt;))&lt;/pre&gt;&lt;pre class="alteven"&gt;    &lt;span class="kwrd"&gt;DROP&lt;/span&gt; &lt;span class="kwrd"&gt;FUNCTION&lt;/span&gt; dbo.fnRegionsToString&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="kwrd"&gt;GO&lt;/span&gt;&lt;/pre&gt;&lt;pre class="alteven"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="kwrd"&gt;CREATE&lt;/span&gt; &lt;span class="kwrd"&gt;FUNCTION&lt;/span&gt; dbo.fnRegionsToString&lt;/pre&gt;&lt;pre class="alteven"&gt;(&lt;/pre&gt;&lt;pre class="alt"&gt;    @CountryRegionCode &lt;span class="kwrd"&gt;varchar&lt;/span&gt;(5)&lt;/pre&gt;&lt;pre class="alteven"&gt;)&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="kwrd"&gt;RETURNS&lt;/span&gt; &lt;span class="kwrd"&gt;varchar&lt;/span&gt;(&lt;span class="kwrd"&gt;Max&lt;/span&gt;)&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="kwrd"&gt;AS&lt;/span&gt;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="kwrd"&gt;BEGIN&lt;/span&gt;&lt;/pre&gt;&lt;pre class="alteven"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre class="alt"&gt;    &lt;span class="kwrd"&gt;DECLARE&lt;/span&gt; @&lt;span class="kwrd"&gt;result&lt;/span&gt; &lt;span class="kwrd"&gt;varchar&lt;/span&gt;(&lt;span class="kwrd"&gt;max&lt;/span&gt;)&lt;/pre&gt;&lt;pre class="alteven"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre class="alt"&gt;    &lt;span class="kwrd"&gt;SELECT&lt;/span&gt;    @&lt;span class="kwrd"&gt;result&lt;/span&gt; = &lt;span class="kwrd"&gt;coalesce&lt;/span&gt;(@&lt;span class="kwrd"&gt;result&lt;/span&gt; + &lt;span class="str"&gt;', '&lt;/span&gt;, &lt;span class="str"&gt;''&lt;/span&gt;) + Name&lt;/pre&gt;&lt;pre class="alteven"&gt;    &lt;span class="kwrd"&gt;FROM&lt;/span&gt;    Person.StateProvince&lt;/pre&gt;&lt;pre class="alt"&gt;    &lt;span class="kwrd"&gt;WHERE&lt;/span&gt;    Person.StateProvince.CountryRegionCode = @CountryRegionCode&lt;/pre&gt;&lt;pre class="alteven"&gt;    &lt;/pre&gt;&lt;pre class="alt"&gt;    &lt;span class="kwrd"&gt;RETURN&lt;/span&gt; @&lt;span class="kwrd"&gt;Result&lt;/span&gt;&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="kwrd"&gt;END&lt;/span&gt;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="kwrd"&gt;GO&lt;/span&gt;&lt;/pre&gt;&lt;pre class="alteven"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="kwrd"&gt;SELECT&lt;/span&gt; Name &lt;span class="kwrd"&gt;AS&lt;/span&gt; Country, dbo.fnRegionsToString(CountryRegionCode) States&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="kwrd"&gt;FROM&lt;/span&gt;         Person.CountryRegion&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="CopyToClipboard" style=""&gt;&lt;div&gt;&lt;a href="javascript:void(0);" onclick="CopyToClipboard_ViewPlain(copyToClipboardc2e8c1f0f660465b8e6cb3f6679e9c44_6368);"&gt;View Plain&lt;/a&gt; | &lt;a href="javascript:void(0);" onclick="CopyToClipboard_Copy(copyToClipboardc2e8c1f0f660465b8e6cb3f6679e9c44_6368);"&gt;Copy To Clipboard&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;
					&lt;script type="text/javascript"&gt;
						var copyToClipboardc2e8c1f0f660465b8e6cb3f6679e9c44_6368 = CopyToClipboard_Strip('IF  EXISTS (SELECT * FROM dbo.sysobjects WHERE [id] = OBJECT_ID(N\'[dbo].[fnRegionsToString]\') AND type in (N\'FN\', N\'IF\', N\'TF\', N\'FS\', N\'FT\'))    DROP FUNCTION dbo.fnRegionsToStringGO CREATE FUNCTION dbo.fnRegionsToString(    @CountryRegionCode varchar(5))RETURNS varchar(Max)ASBEGIN     DECLARE @result varchar(max)     SELECT    @result = coalesce(@result + \', \', \'\') + Name    FROM    Person.StateProvince    WHERE    Person.StateProvince.CountryRegionCode = @CountryRegionCode        RETURN @ResultENDGO SELECT Name AS Country, dbo.fnRegionsToString(CountryRegionCode) StatesFROM         Person.CountryRegion');
					&lt;/script&gt;
&lt;p&gt;This makes for a very clean solution to an otherwise painful problem. So the next time you need to turn a lot of records into a single one, check to see if this technique can help.&lt;/p&gt;&lt;div class="socialBookmarksContainer"&gt;&lt;a rel="nofollow" href="http://digg.com/submit/?url=http://dotnetprofessional.com/blog/post/2008/06/Turn-multiple-rows-into-a-single-string-in-SQL-Server.aspx" target="_blank" title="Digg It!"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/digg_24.png" style="border: 0;" alt="Digg It!" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://www.dzone.com/links/add.html?url=http://dotnetprofessional.com/blog/post/2008/06/Turn-multiple-rows-into-a-single-string-in-SQL-Server.aspx&amp;amp;title=Turn multiple rows into a single string in SQL Server" target="_blank" title="DZone It!"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/dzone_24.png" style="border: 0;" alt="DZone It!" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://www.stumbleupon.com/submit?url=http://dotnetprofessional.com/blog/post/2008/06/Turn-multiple-rows-into-a-single-string-in-SQL-Server.aspx" target="_blank" title="StumbleUpon"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/stumbleupon_24.png" style="border: 0;" alt="StumbleUpon" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://technorati.com/ping?url=http://dotnetprofessional.com/blog/" target="_blank" title="Technorati"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/technorati_24.png" style="border: 0;" alt="Technorati" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://reddit.com/submit?url=http://dotnetprofessional.com/blog/post/2008/06/Turn-multiple-rows-into-a-single-string-in-SQL-Server.aspx&amp;amp;title=Turn multiple rows into a single string in SQL Server" target="_blank" title="Reddit"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/reddit_24.png" style="border: 0;" alt="Reddit" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://del.icio.us/post?url=http://dotnetprofessional.com/blog/post/2008/06/Turn-multiple-rows-into-a-single-string-in-SQL-Server.aspx&amp;amp;title=Turn multiple rows into a single string in SQL Server" target="_blank" title="Del.icio.us"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/delicious_24.png" style="border: 0;" alt="Del.icio.us" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://www.newsvine.com/_wine/save?u=http://dotnetprofessional.com/blog/post/2008/06/Turn-multiple-rows-into-a-single-string-in-SQL-Server.aspx" target="_blank"title="NewsVine"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/newsvine_24.png" style="border: 0;" alt="NewsVine" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://furl.net" target="_blank" title="Furl"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/furl_24.png" style="border: 0;" alt="Furl" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://blinklist.com/submit/" target="_blank" title="BlinkList"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/blinklist_24.png" style="border: 0;" alt="BlinkList" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Dotnetprofessional/~4/339721342" height="1" width="1"/&gt;</description>
      <link>http://feeds.feedburner.com/~r/Dotnetprofessional/~3/339721342/post.aspx</link>
      <author>garrymc</author>
      <comments>http://dotnetprofessional.com/blog/post/2008/06/Turn-multiple-rows-into-a-single-string-in-SQL-Server.aspx#comment</comments>
      <guid isPermaLink="false">http://dotnetprofessional.com/blog/post.aspx?id=47bbbfdf-4c84-464f-9fb8-58a2427f5c3a</guid>
      <pubDate>Fri, 27 Jun 2008 22:56:56 -0700</pubDate>
      <category>SQL</category>
      <dc:publisher>garrymc</dc:publisher>
      <pingback:server>http://dotnetprofessional.com/blog/pingback.axd</pingback:server>
      <pingback:target>http://dotnetprofessional.com/blog/post.aspx?id=47bbbfdf-4c84-464f-9fb8-58a2427f5c3a</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://dotnetprofessional.com/blog/trackback.axd?id=47bbbfdf-4c84-464f-9fb8-58a2427f5c3a</trackback:ping>
      <wfw:comment>http://dotnetprofessional.com/blog/post/2008/06/Turn-multiple-rows-into-a-single-string-in-SQL-Server.aspx#comment</wfw:comment>
      <wfw:commentRss>http://dotnetprofessional.com/blog/syndication.axd?post=47bbbfdf-4c84-464f-9fb8-58a2427f5c3a</wfw:commentRss>
    <feedburner:origLink>http://dotnetprofessional.com/blog/post.aspx?id=47bbbfdf-4c84-464f-9fb8-58a2427f5c3a</feedburner:origLink></item>
    <item>
      <title>Modeling many-to-one (M:1) entity relationships Part II</title>
      <description>&lt;p&gt;This is the second part of the series which discusses the issues around modeling M:1 (many-to-one) relationships. If you've not read the first part, then its advisable that you read that first before continuing with this part. To keep up to date with this and other blog's you might consider registering with the &lt;a title="The dotNetProfessional RSS feed." href="http://www.dotnetprofessional.com/blog/syndication.axd"&gt;RSS feed&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;&lt;a href="http://dotnetprofessional.com/blog/blog/post/2008/06/Modeling-many-to-one-(M1)-entity-relationships-Part-I.aspx"&gt;Part I: The Problem&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Part III: BusinessKey as a value type&lt;/p&gt; &lt;h2&gt;Suggested Solution&lt;/h2&gt; &lt;p&gt;Having covered the issues with M:1 relationships and the three different types I'll now present a potential solution which provides the necessary foreign key information, but in a more domain model fashion. I'll also point out yet another issue with the original logical model when it comes to actually using it, which I'll also offer up a solution for. &lt;/p&gt; &lt;p&gt;Remembering the tree types of M:1 relationships discussed previously, lets see how we can treat them differently:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;strong&gt;Reference: &lt;/strong&gt;As a reference table will typically (should only have one significant column; which must be unique!) only have one column which we can map to as a string just like we did in the logical model. The effect is that instead of having OrderTypeID we have OrderTypeName, both values are unique and therefore provide a 'key' to the OrderType table. As there's nothing else of real interest in the OrderType table, returning only a single field and merging it into the main entity poses little issue but does provide a much more meaningful value than some arbitrary key. In many cases this can avoid a second call to a service or database as we already have the pertinent information.  &lt;li&gt;&lt;strong&gt;Enum:&lt;/strong&gt; An enum table is also much like the reference table, the only difference being that we can also record all the known values as an enum and tie this enum to the entity exactly like we did in the logical model. When saving the data however, we don't attempt to save the enums number value but its name. That is we send &lt;em&gt;Processing&lt;/em&gt; not &lt;em&gt;1&lt;/em&gt;, as the number may have little connection to the back end database, and again we want to remove our system keys as much as possible. Therefore the save is exactly the same as it would be for a reference type, we just represent the 'string' value differently as we know what the allowable ones are.  &lt;li&gt;&lt;strong&gt;Entity:&lt;/strong&gt; The entity type is the most interesting of the types. If you look at the original model vs the one produced by Linq to SQL, you might be thinking, well its basically the same what's wrong with that? Well a few things actually which is the topic of the next section.&lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;Modeling M:1 Entities&lt;/h3&gt; &lt;p&gt;As suggested, modeling reference and enum types are fairly straightforward just requiring an extra join to get the necessary information (which is worth it as the information is useful!). However, I've indicated that the seemingly correct entity M:1 has some issues. The issues I see are:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;The parent entity still has the child key which is a system key, and is most likely useless to a business person.  &lt;li&gt;If you've adopted the Linq to SQL pattern you have the same issues as already discussed with sync issues etc.  &lt;li&gt;If you want to create a new child entity and associate it to the parent you either have to create the entity first (thereby getting its key) or using the Linq to SQL model and attach a new child entity object; which should work fairly well.  &lt;li&gt;Alternative designs may remove the foreign key from the parent and rely on the child telling the parent what the key is. The issue with this is that you must have a full entity as the child even if you are only concerned with the parent. Also adding the association requires the full entity which may not be available at the time of creating a new entity.&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;In the past I've tended to treat entity M:1 relationships as reference relationship types with a single key from the entity being used as its business key. This works fairly well, that is until you get an entity that has a business key that maps to more than a single column, which unfortunately happens quite often. In these occasions, I tended to use the entities GUID if it has one or revert to the system key (hey I need something!). As I didn't want the burden of having to retrieve an entire entity just so I know the keys.&lt;/p&gt; &lt;p&gt;So while having the entire entity would be nice and does better represent our original model it poses a number of limitations especially if you just want to associate a pre-existing child entity to a parent. What would be good is to have just the keys, but then be able to upscale to the full entity when the use case requires it. This is exactly what I propose as the solution to this issue. Instead of having a single value to represent a complex entities M:1 relationship we have what I'm calling a business key entity which only knows about the &lt;strong&gt;unique&lt;/strong&gt; business key for that entity and it acts like a value type. The parent then has a relationship with this business key entity not the full entity. Initially I thought an interface could be used to avoid having a separate business entity but as it turns out you can't serialize a property that has an interface as its return type. That basically means in order to support polymorphism (ie the ability to upscale) we have to use implementation inheritance. The original model is demonstrated below using this new technique:&lt;/p&gt; &lt;p&gt;&lt;a title="Model using suggested approach" href="http://www.dotnetprofessional.com/blog/image.axd?picture=WindowsLiveWriter/ModelingmanytooneM1entityrelationshipsPa_A15E/Model_2.jpg" rel="lightbox"&gt;&lt;img height="210" alt="Model using suggested approach" src="http://www.dotnetprofessional.com/blog/image.axd?picture=WindowsLiveWriter/ModelingmanytooneM1entityrelationshipsPa_A15E/Model_thumb.jpg" width="580"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;For those who prefer to look at code rather than diagrams, here's how the class for the OrderDetail class and Product business key classes look. The other classes follow a similar pattern, if you are keen to see how all the code looks, leave an email and I'll try bundle it all up:&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;div class="csharpcode-wrapper"&gt; &lt;div class="csharpcode"&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:&lt;/span&gt; &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;partial&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; OrderDetailBusinessKey &lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:&lt;/span&gt;     &lt;span class="kwrd"&gt;private&lt;/span&gt; System.Int32 _orderDetailID;&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;   4:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:&lt;/span&gt;     &lt;span class="rem"&gt;//  Business key constructor&lt;/span&gt;&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;   6:&lt;/span&gt;     &lt;span class="kwrd"&gt;public&lt;/span&gt; OrderDetailBusinessKey(System.Int32 orderDetailID)&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;   8:&lt;/span&gt;         _orderDetailID = orderDetailID;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  10:&lt;/span&gt;     &lt;span class="kwrd"&gt;public&lt;/span&gt; OrderDetailBusinessKey(){}&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  12:&lt;/span&gt;     &lt;span class="kwrd"&gt;public&lt;/span&gt; System.Int32 OrderDetailID&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  14:&lt;/span&gt;         get {&lt;span class="kwrd"&gt;return&lt;/span&gt; _orderDetailID;}&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:&lt;/span&gt;         set {_orderDetailID = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  16:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  17:&lt;/span&gt; }&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  18:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  19:&lt;/span&gt; [Serializable]&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  20:&lt;/span&gt; &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;partial&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; OrderDetail&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  21:&lt;/span&gt;     : OrderDetailBusinessKey&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  22:&lt;/span&gt; {&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  23:&lt;/span&gt;     &lt;span class="preproc"&gt;#region&lt;/span&gt; Private Variables&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  24:&lt;/span&gt;     &lt;span class="kwrd"&gt;private&lt;/span&gt; OrderBusinessKey _order;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  25:&lt;/span&gt;     &lt;span class="kwrd"&gt;private&lt;/span&gt; ProductBusinessKey _product;&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  26:&lt;/span&gt;     &lt;span class="kwrd"&gt;private&lt;/span&gt; System.Int32 _quantity;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  27:&lt;/span&gt;     &lt;span class="kwrd"&gt;private&lt;/span&gt; System.Decimal _price;&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  28:&lt;/span&gt;     &lt;span class="kwrd"&gt;private&lt;/span&gt; System.Decimal _total;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  29:&lt;/span&gt;     &lt;span class="rem"&gt;// Variables for relationships&lt;/span&gt;&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  30:&lt;/span&gt;     &lt;span class="preproc"&gt;#endregion&lt;/span&gt;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  31:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  32:&lt;/span&gt;     &lt;span class="preproc"&gt;#region&lt;/span&gt; Constructors&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  33:&lt;/span&gt;     &lt;span class="kwrd"&gt;public&lt;/span&gt; OrderDetail()&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  34:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  35:&lt;/span&gt;         &lt;span class="kwrd"&gt;this&lt;/span&gt;.Initialize();&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  36:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  37:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  38:&lt;/span&gt;     &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  39:&lt;/span&gt;     &lt;span class="rem"&gt;/// This code initializes the domain value types for the generated properties&lt;/span&gt;&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  40:&lt;/span&gt;     &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  41:&lt;/span&gt;     &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;virtual&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Initialize()&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  42:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  43:&lt;/span&gt;         _order = &lt;span class="kwrd"&gt;new&lt;/span&gt; bl.OrderBusinessKey();&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  44:&lt;/span&gt;         _product = &lt;span class="kwrd"&gt;new&lt;/span&gt; bl.ProductBusinessKey();&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  45:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  46:&lt;/span&gt;         &lt;span class="rem"&gt;// Call the Initialize routine in the partial class&lt;/span&gt;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  47:&lt;/span&gt;         &lt;span class="kwrd"&gt;this&lt;/span&gt;.ExtendedInitialize();&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  48:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  49:&lt;/span&gt;     &lt;span class="preproc"&gt;#endregion&lt;/span&gt;&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  50:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  51:&lt;/span&gt;     &lt;span class="preproc"&gt;#region&lt;/span&gt; Public Properties&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  52:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  53:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  54:&lt;/span&gt;     &lt;span class="kwrd"&gt;public&lt;/span&gt; OrderBusinessKey Order&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  55:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  56:&lt;/span&gt;         get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _order; }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  57:&lt;/span&gt;         set { _order = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  58:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  59:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  60:&lt;/span&gt;     &lt;span class="kwrd"&gt;public&lt;/span&gt; ProductBusinessKey Product&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  61:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  62:&lt;/span&gt;         get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _product; }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  63:&lt;/span&gt;         set { _product = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  64:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  65:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  66:&lt;/span&gt;     &lt;span class="kwrd"&gt;public&lt;/span&gt; System.Int32 Quantity&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  67:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  68:&lt;/span&gt;         get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _quantity; }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  69:&lt;/span&gt;         set { _quantity = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  70:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  71:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  72:&lt;/span&gt;     &lt;span class="kwrd"&gt;public&lt;/span&gt; System.Decimal Price&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  73:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  74:&lt;/span&gt;         get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _price; }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  75:&lt;/span&gt;         set { _price = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  76:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  77:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  78:&lt;/span&gt;     &lt;span class="kwrd"&gt;public&lt;/span&gt; System.Decimal Total&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  79:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  80:&lt;/span&gt;         get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _total; }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  81:&lt;/span&gt;         set { _total = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  82:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  83:&lt;/span&gt;     &lt;span class="preproc"&gt;#endregion&lt;/span&gt;&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  84:&lt;/span&gt; }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  85:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  86:&lt;/span&gt; &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;partial&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ProductBusinessKey &lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  87:&lt;/span&gt; {&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  88:&lt;/span&gt;     &lt;span class="kwrd"&gt;private&lt;/span&gt; System.String _productName;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  89:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  90:&lt;/span&gt;     &lt;span class="rem"&gt;//  Business key constructor&lt;/span&gt;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  91:&lt;/span&gt;     &lt;span class="kwrd"&gt;public&lt;/span&gt; ProductBusinessKey(System.String productName)&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  92:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  93:&lt;/span&gt;         _productName = productName;&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  94:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  95:&lt;/span&gt;     &lt;span class="kwrd"&gt;public&lt;/span&gt; ProductBusinessKey(){}&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  96:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  97:&lt;/span&gt;     &lt;span class="kwrd"&gt;public&lt;/span&gt; System.String ProductName&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  98:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  99:&lt;/span&gt;         get {&lt;span class="kwrd"&gt;return&lt;/span&gt; _productName;}&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt; 100:&lt;/span&gt;         set {_productName = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 101:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt; 102:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="CopyToClipboard" style=""&gt;&lt;div&gt;&lt;a href="javascript:void(0);" onclick="CopyToClipboard_ViewPlain(copyToClipboard67c5cd8d47ea424fbcddbccf9b16506e_6356);"&gt;View Plain&lt;/a&gt; | &lt;a href="javascript:void(0);" onclick="CopyToClipboard_Copy(copyToClipboard67c5cd8d47ea424fbcddbccf9b16506e_6356);"&gt;Copy To Clipboard&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;
					&lt;script type="text/javascript"&gt;
						var copyToClipboard67c5cd8d47ea424fbcddbccf9b16506e_6356 = CopyToClipboard_Strip('public partial class OrderDetailBusinessKey    2: {   3:     private System.Int32 _orderDetailID;   4:     5:     //  Business key constructor   6:     public OrderDetailBusinessKey(System.Int32 orderDetailID)   7:     {   8:         _orderDetailID = orderDetailID;   9:     }  10:     public OrderDetailBusinessKey(){}  11:    12:     public System.Int32 OrderDetailID  13:     {  14:         get {return _orderDetailID;}  15:         set {_orderDetailID = value; }  16:     }  17: }  18:    19: [Serializable]  20: public partial class OrderDetail  21:     : OrderDetailBusinessKey  22: {  23:     #region Private Variables  24:     private OrderBusinessKey _order;  25:     private ProductBusinessKey _product;  26:     private System.Int32 _quantity;  27:     private System.Decimal _price;  28:     private System.Decimal _total;  29:     // Variables for relationships  30:     #endregion  31:    32:     #region Constructors  33:     public OrderDetail()  34:     {  35:         this.Initialize();  36:     }  37:    38:     /// &amp;lt;summary&amp;gt;  39:     /// This code initializes the domain value types for the generated properties  40:     /// &amp;lt;/summary&amp;gt;  41:     protected virtual void Initialize()  42:     {  43:         _order = new bl.OrderBusinessKey();  44:         _product = new bl.ProductBusinessKey();  45:    46:         // Call the Initialize routine in the partial class  47:         this.ExtendedInitialize();  48:     }  49:     #endregion  50:    51:     #region Public Properties  52:    53:    54:     public OrderBusinessKey Order  55:     {  56:         get { return _order; }  57:         set { _order = value; }  58:     }  59:    60:     public ProductBusinessKey Product  61:     {  62:         get { return _product; }  63:         set { _product = value; }  64:     }  65:    66:     public System.Int32 Quantity  67:     {  68:         get { return _quantity; }  69:         set { _quantity = value; }  70:     }  71:    72:     public System.Decimal Price  73:     {  74:         get { return _price; }  75:         set { _price = value; }  76:     }  77:    78:     public System.Decimal Total  79:     {  80:         get { return _total; }  81:         set { _total = value; }  82:     }  83:     #endregion  84: }  85:    86: public partial class ProductBusinessKey   87: {  88:     private System.String _productName;  89:    90:     //  Business key constructor  91:     public ProductBusinessKey(System.String productName)  92:     {  93:         _productName = productName;  94:     }  95:     public ProductBusinessKey(){}  96:    97:     public System.String ProductName  98:     {  99:         get {return _productName;} 100:         set {_productName = value; } 101:     } 102: }');
					&lt;/script&gt;
&lt;p&gt;At first glance this might seem overly complex, but if you think about what's happening its not. The perceived complexity comes from the fact that every 'entity' now has a base business key class. While I've shown them all on the diagram, in general they wouldn't need to be seen, just knowing that the property is type ProductBusinessKey would be enough without actually showing the relationship. However, looking at the model, we can see that all but the primary key IDs have been eliminated from our domain model and it looks surprisingly similar to what our original logical model looked like. This approach provides a number of benefits despite its slightly more complex model:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Flexible persistence:&lt;/strong&gt; You can add either an existing entity to a parent via its business key or the entire entity. The code used to persist the relationship can simply check what its type is to determine if a full entity needs updating/saving or just an association is required based on the business key. Also you don't have the duplication of keys, so you can write Order.Status = Status.Shipped or even OrderDetail.Product.ProductName = "Product B" (assuming you are using the BusinessKey not the full entity) which seems very intuitive. 
&lt;li&gt;&lt;strong&gt;Eliminate foreign key IDs:&lt;/strong&gt; Although its true that some entities don't have business or natural keys. In these situations, you're left with either using a GUID if available or the system primary key. 
&lt;li&gt;&lt;strong&gt;Entities are more useful:&lt;/strong&gt; Your entities now having gotten rid of meaningless keys (from the business perspective) can do more without requesting more data from the server. Ie if you wanted to list the OrderDetails chances are you could get away with displaying OrderDetail.Product.ProductName to the user and not have to worry about retrieving more detail about a product unless specifically requested. 
&lt;li&gt;&lt;strong&gt;SOA friendly:&lt;/strong&gt; This design is more friendly as the entities resemble documents more than they represent a table, as such they make for a much friendlier XML representation which is now human readable ie instead of seeing IDs for products you'll see the actual product names.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;So what's the downside of the approach? From what I can see the main downside is the amount of effort required to make it all work. There are a lot more classes that need creating and you do have to do some extra joins in your selects too; however I believe it reduces complexity overall as the model is more natural and cleaner to work with. However, these issues can be mitigated via code generation, and the good news is that I'll be releasing something fairly soon (notice the vague reference) that implements this model. The sample above was completely code generated. If anyone is interested in being an alpha/beta tester, send me an email via the contacts page or leave a comment.&lt;/p&gt;
&lt;p&gt;While this might look like the end of the discussion, there are still a few things that need addressing including inheritance and the concept of the business key as a value type. These will be covered in the last part of this series, so check back soon.&lt;/p&gt;
&lt;p&gt;This discussion is to obtain feedback on how others feel about the approach I'm taking with my models and open a discussion on how best to model these M:1 relationships. I look forward to any feedback, positive or negative on the approach.&lt;/p&gt;&lt;div class="socialBookmarksContainer"&gt;&lt;a rel="nofollow" href="http://digg.com/submit/?url=http://dotnetprofessional.com/blog/post/2008/06/Modeling-many-to-one-(M1)-entity-relationships-Part-II.aspx" target="_blank" title="Digg It!"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/digg_24.png" style="border: 0;" alt="Digg It!" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://www.dzone.com/links/add.html?url=http://dotnetprofessional.com/blog/post/2008/06/Modeling-many-to-one-(M1)-entity-relationships-Part-II.aspx&amp;amp;title=Modeling many-to-one (M:1) entity relationships Part II" target="_blank" title="DZone It!"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/dzone_24.png" style="border: 0;" alt="DZone It!" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://www.stumbleupon.com/submit?url=http://dotnetprofessional.com/blog/post/2008/06/Modeling-many-to-one-(M1)-entity-relationships-Part-II.aspx" target="_blank" title="StumbleUpon"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/stumbleupon_24.png" style="border: 0;" alt="StumbleUpon" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://technorati.com/ping?url=http://dotnetprofessional.com/blog/" target="_blank" title="Technorati"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/technorati_24.png" style="border: 0;" alt="Technorati" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://reddit.com/submit?url=http://dotnetprofessional.com/blog/post/2008/06/Modeling-many-to-one-(M1)-entity-relationships-Part-II.aspx&amp;amp;title=Modeling many-to-one (M:1) entity relationships Part II" target="_blank" title="Reddit"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/reddit_24.png" style="border: 0;" alt="Reddit" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://del.icio.us/post?url=http://dotnetprofessional.com/blog/post/2008/06/Modeling-many-to-one-(M1)-entity-relationships-Part-II.aspx&amp;amp;title=Modeling many-to-one (M:1) entity relationships Part II" target="_blank" title="Del.icio.us"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/delicious_24.png" style="border: 0;" alt="Del.icio.us" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://www.newsvine.com/_wine/save?u=http://dotnetprofessional.com/blog/post/2008/06/Modeling-many-to-one-(M1)-entity-relationships-Part-II.aspx" target="_blank"title="NewsVine"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/newsvine_24.png" style="border: 0;" alt="NewsVine" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://furl.net" target="_blank" title="Furl"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/furl_24.png" style="border: 0;" alt="Furl" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://blinklist.com/submit/" target="_blank" title="BlinkList"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/blinklist_24.png" style="border: 0;" alt="BlinkList" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Dotnetprofessional/~4/339721343" height="1" width="1"/&gt;</description>
      <link>http://feeds.feedburner.com/~r/Dotnetprofessional/~3/339721343/post.aspx</link>
      <author>garrymc</author>
      <comments>http://dotnetprofessional.com/blog/post/2008/06/Modeling-many-to-one-(M1)-entity-relationships-Part-II.aspx#comment</comments>
      <guid isPermaLink="false">http://dotnetprofessional.com/blog/post.aspx?id=52ca981c-db9f-46b7-87fd-faf8ed7dcfe8</guid>
      <pubDate>Wed, 25 Jun 2008 19:00:13 -0700</pubDate>
      <category>.NET 2.0</category>
      <category>Framework</category>
      <category>Modeling</category>
      <dc:publisher>garrymc</dc:publisher>
      <pingback:server>http://dotnetprofessional.com/blog/pingback.axd</pingback:server>
      <pingback:target>http://dotnetprofessional.com/blog/post.aspx?id=52ca981c-db9f-46b7-87fd-faf8ed7dcfe8</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://dotnetprofessional.com/blog/trackback.axd?id=52ca981c-db9f-46b7-87fd-faf8ed7dcfe8</trackback:ping>
      <wfw:comment>http://dotnetprofessional.com/blog/post/2008/06/Modeling-many-to-one-(M1)-entity-relationships-Part-II.aspx#comment</wfw:comment>
      <wfw:commentRss>http://dotnetprofessional.com/blog/syndication.axd?post=52ca981c-db9f-46b7-87fd-faf8ed7dcfe8</wfw:commentRss>
    <feedburner:origLink>http://dotnetprofessional.com/blog/post.aspx?id=52ca981c-db9f-46b7-87fd-faf8ed7dcfe8</feedburner:origLink></item>
    <item>
      <title>Modeling many-to-one (M:1) entity relationships Part I</title>
      <description>&lt;p&gt;Designing a domain model can be a tough job and if you're lucky enough to start from scratch then it becomes even tougher once you apply it to the physical database model. Over the next few posts I' like to discuss the issues we encounter when modeling this relationship type, examine the way its 'normally' done and then present an alternative that I believe presents a more domain model centric view of the world. The series will be broken up into the following sections, with this being the first. To keep up to date with this and other blog's you might consider registering with the &lt;a title="The dotNetProfessional RSS feed." href="http://www.dotnetprofessional.com/blog/syndication.axd"&gt;RSS feed&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;Part I: The Problem&lt;/p&gt; &lt;p&gt;&lt;a title="Part II: Suggested Solution" href="http://dotnetprofessional.com/blog/blog/post/2008/06/Modeling-many-to-one-(M1)-entity-relationships-Part-II.aspx"&gt;Part II: Suggested Solution&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Part III: BusinessKey as a value type&lt;/p&gt; &lt;p&gt;The main issue when designing a domain model is that they don't have these oddities called foreign keys, as the relationships are known by association. However, once you turn your domain model into a database schema we have to start adding all these extra keys, which get worse when you have a M:M (many-to-many) relationship! In this post I'd like to discuss how we normally model the M:1 (many-to-one) relationship and its pitfalls. &lt;/p&gt; &lt;h2&gt;The Problem&lt;/h2&gt; &lt;p&gt;When designing a domain model (entity model) in UML its unlikely that you'd include foreign key relationships as part of your design as this is a database concept rather than a domain concept. If we take a very simple and arguably contrived example (its very basic just to highlight the concepts I want to discuss) of an Order it might look something like this (note I'm using the VS class designer which doesn't support multiplicities hence I have to use two associations to highlight relationships):&lt;/p&gt; &lt;p&gt;&lt;a title="Logical Model" href="http://www.dotnetprofessional.com/blog/image.axd?picture=WindowsLiveWriter/ModelingmanytooneM1entityrelationshipsPa_8644/LogicalModel_2.jpg" rel="lightbox"&gt;&lt;img height="244" alt="Logica Model" src="http://www.dotnetprofessional.com/blog/image.axd?picture=WindowsLiveWriter/ModelingmanytooneM1entityrelationshipsPa_8644/LogicalModel_thumb.jpg" width="580"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;In this example we have three different types of M:1 relationships being modeled, which are:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;strong&gt;Entity &lt;/strong&gt;- The OrderDetail --&amp;gt; Product and Oder--&amp;gt;Customer are M:1 relationships which map to other entities within the business domain.  &lt;li&gt;&lt;strong&gt;Reference &lt;/strong&gt;- The Order.OrderType property is one that is restricted by a known set of values. However, this set of values can change over the life time of the application. That is its data driven and so the current values can't be coded directly within the application. Also a reference value is usually defined as a single field with no other business properties.  &lt;li&gt;&lt;strong&gt;Enum&lt;/strong&gt; - The Order.Status property is also restricted by a known set of values. However, unlike a reference type the values don't or can't change. These values typically drive logic which is set during design, adding a new value after deployment wouldn't add value as the application wouldn't know what to do with it. &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Now that I've defined the different M:1 relationship types, they would typically be modeled in the database all the same way as foreign key constraints to their respective tables. The following diagram shows the ER (Entity Relationship) diagram of the physical database model.&lt;/p&gt; &lt;p&gt;&lt;a title="Physical Database Model" href="http://www.dotnetprofessional.com/blog/image.axd?picture=WindowsLiveWriter/ModelingmanytooneM1entityrelationshipsPa_8644/PhysicalModel_2.jpg" rel="lightbox"&gt;&lt;img height="251" alt="Physical Database Model" src="http://www.dotnetprofessional.com/blog/image.axd?picture=WindowsLiveWriter/ModelingmanytooneM1entityrelationshipsPa_8644/PhysicalModel_thumb.jpg" width="580"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;So the next step in modeling our sample is to create the actual business entities that we can use in a real application, taking into account how our data is physically stored so that we can map our logical to the physical as easy as possible. This of course is where things typically start to deviate from our nice logical model. We have to take these foreign keys into consideration as the database needs them, so typically we end up with something more like the following figure than our original logical model. The following was created using Linq for SQL, which like most O/RMs (the Entity Framework will improve on this) will create something like the following:&lt;/p&gt; &lt;p&gt;&lt;a title="Linq to SQL Model" href="http://www.dotnetprofessional.com/blog/image.axd?picture=WindowsLiveWriter/ModelingmanytooneM1entityrelationshipsPa_8644/Linq-Model_2.jpg" rel="lightbox"&gt;&lt;img height="341" alt="Linq to SQL Model" src="http://www.dotnetprofessional.com/blog/image.axd?picture=WindowsLiveWriter/ModelingmanytooneM1entityrelationshipsPa_8644/Linq-Model_thumb.jpg" width="580"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;You'll notice from this model that it more resembles the database model than it does our original logical model. We have an extra entity in the OrderType which we'd probably have in our logical too, to allow for maintenance but we didn't need to tie this object to our Order entity. The changes that were made to our original model can be summarized as:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Simple types are now complex types, namely instead of a simple enum or string we now have full entities with their associated complexities.  &lt;li&gt;Our 'domain' entities now have system keys liberally scattered throughout to support persistence back to the database. &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;We also have the following issues as a result of this:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;We expose a lot of internal information about our database when we expose foreign keys, exposing this data presents a security risk as a hacker may attempt to corrupt your data by altering the primary or foreign keys. This becomes a bigger issue when you expose your data via web services.&amp;nbsp; &lt;li&gt;In the case of Linq to SQL we also have duplication of foreign key fields, namely we have both an OrderTypeID (foreign key field) and an object reference to the OrderType entity. This just looks plain ugly! Also lets say you want to change the OrderType to a different one, if you change the OrderTypeID from 1 to 2, and you did have an OrderType entity associated at the time, you'd be out of sync! The entity version of the OrderType wouldn't match the change you've just made. In the Linq to SQL architecture you're not even allowed to change the foreign key once its been set! You have to change the OrderType entity which will then update the Order.OrderTypeID. Which only goes to highlight the problems. &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;So now that I've expressed the issue and the potential problems with this type of design which is an all to common pattern, with the exception of the double foreign key reference that Linq to SQL uses . The question becomes why? The reasons as I see it are two fold:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Effort, it takes some effort to design more closely to the original logical model  &lt;li&gt;Architectural/Technical in that we need those damn keys, so the issue is how do we make a nicer model without loosing the essential information we need? &lt;/li&gt;&lt;/ol&gt; &lt;p&gt;The next part of the series will examine what we can do to fix this situation and bring our model back in line with what we originally intended.&lt;/p&gt;&lt;div class="socialBookmarksContainer"&gt;&lt;a rel="nofollow" href="http://digg.com/submit/?url=http://dotnetprofessional.com/blog/post/2008/06/Modeling-many-to-one-(M1)-entity-relationships-Part-I.aspx" target="_blank" title="Digg It!"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/digg_24.png" style="border: 0;" alt="Digg It!" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://www.dzone.com/links/add.html?url=http://dotnetprofessional.com/blog/post/2008/06/Modeling-many-to-one-(M1)-entity-relationships-Part-I.aspx&amp;amp;title=Modeling many-to-one (M:1) entity relationships Part I" target="_blank" title="DZone It!"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/dzone_24.png" style="border: 0;" alt="DZone It!" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://www.stumbleupon.com/submit?url=http://dotnetprofessional.com/blog/post/2008/06/Modeling-many-to-one-(M1)-entity-relationships-Part-I.aspx" target="_blank" title="StumbleUpon"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/stumbleupon_24.png" style="border: 0;" alt="StumbleUpon" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://technorati.com/ping?url=http://dotnetprofessional.com/blog/" target="_blank" title="Technorati"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/technorati_24.png" style="border: 0;" alt="Technorati" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://reddit.com/submit?url=http://dotnetprofessional.com/blog/post/2008/06/Modeling-many-to-one-(M1)-entity-relationships-Part-I.aspx&amp;amp;title=Modeling many-to-one (M:1) entity relationships Part I" target="_blank" title="Reddit"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/reddit_24.png" style="border: 0;" alt="Reddit" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://del.icio.us/post?url=http://dotnetprofessional.com/blog/post/2008/06/Modeling-many-to-one-(M1)-entity-relationships-Part-I.aspx&amp;amp;title=Modeling many-to-one (M:1) entity relationships Part I" target="_blank" title="Del.icio.us"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/delicious_24.png" style="border: 0;" alt="Del.icio.us" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://www.newsvine.com/_wine/save?u=http://dotnetprofessional.com/blog/post/2008/06/Modeling-many-to-one-(M1)-entity-relationships-Part-I.aspx" target="_blank"title="NewsVine"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/newsvine_24.png" style="border: 0;" alt="NewsVine" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://furl.net" target="_blank" title="Furl"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/furl_24.png" style="border: 0;" alt="Furl" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://blinklist.com/submit/" target="_blank" title="BlinkList"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/blinklist_24.png" style="border: 0;" alt="BlinkList" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Dotnetprofessional/~4/339721344" height="1" width="1"/&gt;</description>
      <link>http://feeds.feedburner.com/~r/Dotnetprofessional/~3/339721344/post.aspx</link>
      <author>garrymc</author>
      <comments>http://dotnetprofessional.com/blog/post/2008/06/Modeling-many-to-one-(M1)-entity-relationships-Part-I.aspx#comment</comments>
      <guid isPermaLink="false">http://dotnetprofessional.com/blog/post.aspx?id=df81b12d-6a6c-48a9-b568-e67a5869d93e</guid>
      <pubDate>Sun, 22 Jun 2008 13:06:18 -0700</pubDate>
      <category>.NET 2.0</category>
      <category>Framework</category>
      <category>Modeling</category>
      <dc:publisher>garrymc</dc:publisher>
      <pingback:server>http://dotnetprofessional.com/blog/pingback.axd</pingback:server>
      <pingback:target>http://dotnetprofessional.com/blog/post.aspx?id=df81b12d-6a6c-48a9-b568-e67a5869d93e</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://dotnetprofessional.com/blog/trackback.axd?id=df81b12d-6a6c-48a9-b568-e67a5869d93e</trackback:ping>
      <wfw:comment>http://dotnetprofessional.com/blog/post/2008/06/Modeling-many-to-one-(M1)-entity-relationships-Part-I.aspx#comment</wfw:comment>
      <wfw:commentRss>http://dotnetprofessional.com/blog/syndication.axd?post=df81b12d-6a6c-48a9-b568-e67a5869d93e</wfw:commentRss>
    <feedburner:origLink>http://dotnetprofessional.com/blog/post.aspx?id=df81b12d-6a6c-48a9-b568-e67a5869d93e</feedburner:origLink></item>
    <item>
      <title>Create a full entity class diagram with a T4 template</title>
      <description>&lt;p&gt;I've just released another sample for the Database Explorer API, this time using the built in features of Visual Studio 2008 (should work with VS 2005 with a download of the SDK). Visual Studio 2008 comes with a built in code generator known as T4. While the built in editing experience leaves a bit to be desired the free &lt;a href="http://www.t4editor.net/" target="_blank"&gt;T4 editor&lt;/a&gt; by Clarius Consulting goes a long way to making it workable. If you download the editor, it indicates that the time bomb expires in Jan 1, 2008; this however isn't the case as they're still working on the next release.&lt;/p&gt; &lt;p&gt;This sample creates a fairly decent (not perfect by any means) set of entities which you can then easily drop on to a class designer and get a good feel for how your domain model looks. It has support for all but the recursive relationship type, which could be added as the API does support this. This sample is provided to show how much you can do with both T4 and the API in only a small amout of code. I've included a screen shot from the Adventure Works sample, which as you can see supports many relationship types. The sample download includes the results run against the AdventureWorks sample database.&lt;/p&gt; &lt;p&gt;To download the new sample visit the projects &lt;a href="https://www.codeplex.com/Release/ProjectReleases.aspx?ProjectName=dnpFramework&amp;amp;ReleaseId=11811" target="_blank"&gt;CodePlex page&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;Remember to provide as much feed back on the samples and API as you can. Enjoy!&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.dotnetprofessional.com/blog/image.axd?picture=WindowsLiveWriter/CreateafullentityclassdiagramwithaT4temp_13FDE/Entity%20Model_2.png" rel="lightbox"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="134" alt="Entity Model" src="http://www.dotnetprofessional.com/blog/image.axd?picture=WindowsLiveWriter/CreateafullentityclassdiagramwithaT4temp_13FDE/Entity%20Model_thumb.png" width="244" border="0"&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="socialBookmarksContainer"&gt;&lt;a rel="nofollow" href="http://digg.com/submit/?url=http://dotnetprofessional.com/blog/post/2008/03/Create-a-full-entity-class-diagram-with-a-T4-template.aspx" target="_blank" title="Digg It!"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/digg_24.png" style="border: 0;" alt="Digg It!" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://www.dzone.com/links/add.html?url=http://dotnetprofessional.com/blog/post/2008/03/Create-a-full-entity-class-diagram-with-a-T4-template.aspx&amp;amp;title=Create a full entity class diagram with a T4 template" target="_blank" title="DZone It!"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/dzone_24.png" style="border: 0;" alt="DZone It!" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://www.stumbleupon.com/submit?url=http://dotnetprofessional.com/blog/post/2008/03/Create-a-full-entity-class-diagram-with-a-T4-template.aspx" target="_blank" title="StumbleUpon"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/stumbleupon_24.png" style="border: 0;" alt="StumbleUpon" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://technorati.com/ping?url=http://dotnetprofessional.com/blog/" target="_blank" title="Technorati"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/technorati_24.png" style="border: 0;" alt="Technorati" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://reddit.com/submit?url=http://dotnetprofessional.com/blog/post/2008/03/Create-a-full-entity-class-diagram-with-a-T4-template.aspx&amp;amp;title=Create a full entity class diagram with a T4 template" target="_blank" title="Reddit"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/reddit_24.png" style="border: 0;" alt="Reddit" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://del.icio.us/post?url=http://dotnetprofessional.com/blog/post/2008/03/Create-a-full-entity-class-diagram-with-a-T4-template.aspx&amp;amp;title=Create a full entity class diagram with a T4 template" target="_blank" title="Del.icio.us"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/delicious_24.png" style="border: 0;" alt="Del.icio.us" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://www.newsvine.com/_wine/save?u=http://dotnetprofessional.com/blog/post/2008/03/Create-a-full-entity-class-diagram-with-a-T4-template.aspx" target="_blank"title="NewsVine"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/newsvine_24.png" style="border: 0;" alt="NewsVine" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://furl.net" target="_blank" title="Furl"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/furl_24.png" style="border: 0;" alt="Furl" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://blinklist.com/submit/" target="_blank" title="BlinkList"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/blinklist_24.png" style="border: 0;" alt="BlinkList" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Dotnetprofessional/~4/339721346" height="1" width="1"/&gt;</description>
      <link>http://feeds.feedburner.com/~r/Dotnetprofessional/~3/339721346/post.aspx</link>
      <author>garrymc</author>
      <comments>http://dotnetprofessional.com/blog/post/2008/03/Create-a-full-entity-class-diagram-with-a-T4-template.aspx#comment</comments>
      <guid isPermaLink="false">http://dotnetprofessional.com/blog/post.aspx?id=7f5ad734-97df-4e9b-90d7-cd7019ca5f32</guid>
      <pubDate>Wed, 26 Mar 2008 05:42:02 -0700</pubDate>
      <category>.NET 3.5</category>
      <category>Framework</category>
      <category>Visual Studio</category>
      <dc:publisher>garrymc</dc:publisher>
      <pingback:server>http://dotnetprofessional.com/blog/pingback.axd</pingback:server>
      <pingback:target>http://dotnetprofessional.com/blog/post.aspx?id=7f5ad734-97df-4e9b-90d7-cd7019ca5f32</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://dotnetprofessional.com/blog/trackback.axd?id=7f5ad734-97df-4e9b-90d7-cd7019ca5f32</trackback:ping>
      <wfw:comment>http://dotnetprofessional.com/blog/post/2008/03/Create-a-full-entity-class-diagram-with-a-T4-template.aspx#comment</wfw:comment>
      <wfw:commentRss>http://dotnetprofessional.com/blog/syndication.axd?post=7f5ad734-97df-4e9b-90d7-cd7019ca5f32</wfw:commentRss>
    <feedburner:origLink>http://dotnetprofessional.com/blog/post.aspx?id=7f5ad734-97df-4e9b-90d7-cd7019ca5f32</feedburner:origLink></item>
    <item>
      <title>Learning DSL tools with Videos!</title>
      <description>&lt;p&gt;I'm in the process of getting up to speed with DSL tools, and while there's a whole lot of info out there, at the end of a long day I'd prefer to watch a video on a new subject rather than pour over the written docs, but trying to locate all the video's can be difficult, and even more if you want to view them in the right order. Well this is my effort to make things a little easier. Unless otherwise stated these videos's relate to Visual Studio 2008 edition of DSL tools, as I discover more DSL video's I'll add them to the list. If you know of a good one I've missed, leave a comment and I'll get it added. &lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Presenter:&amp;nbsp; &lt;/strong&gt;&lt;a href="http://hilton.giesenow.com/" target="_blank"&gt;&lt;strong&gt;Hilton Giesenow&lt;/strong&gt;&lt;/a&gt;&lt;em&gt;&lt;strong&gt; &lt;/strong&gt;&lt;/em&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://download.microsoft.com/download/4/f/2/4f2c5ab5-f95a-40e7-8e08-d427f7ef29d7/WinVideo-Extensibility-CreateAndUseT4Templates.wmv" target="_blank"&gt;How Do I: Create And Use T4 Templates?&lt;/a&gt;&lt;/p&gt; &lt;h3&gt;&amp;nbsp;&lt;/h3&gt; &lt;p&gt;&lt;strong&gt;Presenter: &lt;/strong&gt;&lt;a href="http://www.alchemysoftware.co.za" target="_blank"&gt;&lt;strong&gt;Dylan Miles&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://download.microsoft.com/download/7/1/2/712cdc62-1cb4-4282-bf75-a12fc7d4803f/WinVideo-Extensibility-DSLTools-GettingStarted.wmv" target="_blank"&gt;How Do I: Get Started with the Visual Studio Domain Specific Languages?&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&lt;a href="http://download.microsoft.com/download/0/5/3/053d7a6b-d845-47f9-8f10-4aada2264a6e/WinVideo-Extensibility-DSLTools-CreateAndCustomize.wmv"&gt;How Do I: Create and Customize My Domain Specific Language?&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://download.microsoft.com/download/d/5/c/d5ce892e-447e-46e4-a496-990ebf40d4d0/WinVideo-Extensibility-DSLTools-AdvancedCustomization.wmv" target="_blank"&gt;How Do I: Use Advanced Customization?&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&lt;a href="http://download.microsoft.com/download/4/2/a/42aaf634-df86-47cf-a9b4-8dbf84c3cdff/WinVideo-Extensibility-DSLTools-GeneratingCode.wmv" target="_blank"&gt;How Do I: Generate Code from my Domain Specific Language Using DSL Tools?&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&lt;a href="http://download.microsoft.com/download/8/f/8/8f89212c-7ef2-4631-84e8-eb26742bb2a2/WinVideo-Extensibility-MultiProjectTemplate.wmv" target="_blank"&gt;How Do I: Create a Multi Project Template?&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;For those interested in DSL tools and need a rich database schema API to go with it, I've developed the &lt;a href="http://dotnetprofessional.com/blog/blog/post/2008/03/Database-Explorer-API-beta-released.aspx"&gt;Database Explorer API&lt;/a&gt; which provides a rich model to access your database schemas. This API is part of the larger &lt;a href="http://dotnetprofessional.com/blog/blog/page/dnpFramework.aspx"&gt;dnp.Framework&lt;/a&gt; which will also include a Domain Model API amongst other things. Register for the &lt;a href="http://dotnetprofessional.com/blog/blog/syndication.axd" target="_blank"&gt;RSS feed&lt;/a&gt; to keep updated on any updates.&lt;/p&gt;&lt;div class="socialBookmarksContainer"&gt;&lt;a rel="nofollow" href="http://digg.com/submit/?url=http://dotnetprofessional.com/blog/post/2008/03/Learning-DSL-tools-with-Videos!.aspx" target="_blank" title="Digg It!"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/digg_24.png" style="border: 0;" alt="Digg It!" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://www.dzone.com/links/add.html?url=http://dotnetprofessional.com/blog/post/2008/03/Learning-DSL-tools-with-Videos!.aspx&amp;amp;title=Learning DSL tools with Videos!" target="_blank" title="DZone It!"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/dzone_24.png" style="border: 0;" alt="DZone It!" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://www.stumbleupon.com/submit?url=http://dotnetprofessional.com/blog/post/2008/03/Learning-DSL-tools-with-Videos!.aspx" target="_blank" title="StumbleUpon"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/stumbleupon_24.png" style="border: 0;" alt="StumbleUpon" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://technorati.com/ping?url=http://dotnetprofessional.com/blog/" target="_blank" title="Technorati"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/technorati_24.png" style="border: 0;" alt="Technorati" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://reddit.com/submit?url=http://dotnetprofessional.com/blog/post/2008/03/Learning-DSL-tools-with-Videos!.aspx&amp;amp;title=Learning DSL tools with Videos!" target="_blank" title="Reddit"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/reddit_24.png" style="border: 0;" alt="Reddit" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://del.icio.us/post?url=http://dotnetprofessional.com/blog/post/2008/03/Learning-DSL-tools-with-Videos!.aspx&amp;amp;title=Learning DSL tools with Videos!" target="_blank" title="Del.icio.us"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/delicious_24.png" style="border: 0;" alt="Del.icio.us" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://www.newsvine.com/_wine/save?u=http://dotnetprofessional.com/blog/post/2008/03/Learning-DSL-tools-with-Videos!.aspx" target="_blank"title="NewsVine"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/newsvine_24.png" style="border: 0;" alt="NewsVine" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://furl.net" target="_blank" title="Furl"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/furl_24.png" style="border: 0;" alt="Furl" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://blinklist.com/submit/" target="_blank" title="BlinkList"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/blinklist_24.png" style="border: 0;" alt="BlinkList" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Dotnetprofessional/~4/339721347" height="1" width="1"/&gt;</description>
      <link>http://feeds.feedburner.com/~r/Dotnetprofessional/~3/339721347/post.aspx</link>
      <author>garrymc</author>
      <comments>http://dotnetprofessional.com/blog/post/2008/03/Learning-DSL-tools-with-Videos!.aspx#comment</comments>
      <guid isPermaLink="false">http://dotnetprofessional.com/blog/post.aspx?id=805828dc-95ab-4a19-bf49-305189f793f0</guid>
      <pubDate>Fri, 21 Mar 2008 08:35:20 -0700</pubDate>
      <category>.NET 3.5</category>
      <category>Framework</category>
      <category>Visual Studio</category>
      <dc:publisher>garrymc</dc:publisher>
      <pingback:server>http://dotnetprofessional.com/blog/pingback.axd</pingback:server>
      <pingback:target>http://dotnetprofessional.com/blog/post.aspx?id=805828dc-95ab-4a19-bf49-305189f793f0</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://dotnetprofessional.com/blog/trackback.axd?id=805828dc-95ab-4a19-bf49-305189f793f0</trackback:ping>
      <wfw:comment>http://dotnetprofessional.com/blog/post/2008/03/Learning-DSL-tools-with-Videos!.aspx#comment</wfw:comment>
      <wfw:commentRss>http://dotnetprofessional.com/blog/syndication.axd?post=805828dc-95ab-4a19-bf49-305189f793f0</wfw:commentRss>
    <feedburner:origLink>http://dotnetprofessional.com/blog/post.aspx?id=805828dc-95ab-4a19-bf49-305189f793f0</feedburner:origLink></item>
    <item>
      <title>Database Explorer API beta released</title>
      <description>&lt;p&gt;For anyone that's read my blog entries you've seen me make mention to a framework that I've been working on. Well today marks the release of the first beta of part of that framework. The Database Explorer API, is a database schema API that is designed to make accessing database schema information easy and intuitive. &lt;/p&gt; &lt;p&gt;The API has support for schemas, tables, views, indexes, constraints, relationships ie 1-1, 1-M, M-M, M-1 and recursion. While its original goal was as a replacement for the SchemaExplorer API provided with the Code Smith product, its uses are most definitely not limited to code generation. The API has no dependencies on any other libraries except the ones required to run your database. So if you're a user of &lt;a title="MyGeneration code generation tool" href="http://www.mygenerationsoftware.com/portal/default.aspx" target="_blank"&gt;MyGeneration&lt;/a&gt;, &lt;a title="ArchAngel is a top tier code generation tool with advanced features" href="http://www.slyce.com/ArchAngel/" target="_blank"&gt;ArchAngel&lt;/a&gt; or some other code generation tool, or even if you want to use it in a windows form application you'll only have to reference the dll's to get started; oh and its free too!&lt;/p&gt; &lt;p&gt;The API is fairly complete but does lack support for stored procedures, functions, and retrieving contents of views. However, these are slated for a future release and any feed back on which are more important would be appreciated.&lt;a href="http://dotnetprofessional.com/blog/image.axd?picture=WindowsLiveWriter/DatabaseExplorerAPIbetareleased_F19A/ConsoleSample_2.jpg" rel="lightbox"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; margin: 10px 5px 10px 10px; border-right-width: 0px" height="125" alt="ConsoleSample" src="http://dotnetprofessional.com/blog/image.axd?picture=WindowsLiveWriter/DatabaseExplorerAPIbetareleased_F19A/ConsoleSample_thumb.jpg" width="244" align="right" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;At present the API is in beta and only supports SQL Server 2005, however the provider model being used can easily be used to support other databases. If you are working with another database I'd be happy to work with you to get that database supported.&lt;/p&gt; &lt;p&gt;I've tried to supply a reasonable about of documentation and a few samples (which I'll blog about in more detail over the next week or so) to help get you up and running fast, because I know if it takes more than 10 minutes to get a feel for something, its probably too hard. For those not familiar with Code Smith I've just completed a sample using a console app so you can see it works as easy without Code Smith. The sample is the same as the one detailed in the &lt;a title="Code Smith samples tutorial" href="http://dotnetprofessional.com/blog/blog/page/blog/page/Database-Explorer-API-Overview.aspx"&gt;API overview&lt;/a&gt; so check that out for more details.&lt;/p&gt; &lt;p&gt;As this is a beta I welcome all feed back, positive or negative (though keep it constructive) and I intend to keep releasing updates regularly. To keep updated, I'd recommend registering with the &lt;a title="Register for this blogs RSS feed." href="blog/syndication.axd" target="_blank"&gt;rss feed&lt;/a&gt;. The following links provide you with more information about the current release and what to expect in future releases.&lt;/p&gt; &lt;p&gt;&lt;a title="dnp.Framework" href="blog/page/dnpFramework.aspx"&gt;dnp.Framework&lt;/a&gt;&amp;nbsp; - Provides a summary of the framework and its components. You can also download the framework here.&lt;/p&gt; &lt;p&gt;&lt;a href="blog/page/Database-Explorer-API-Overview.aspx"&gt;Database Explorer API Overview&lt;/a&gt; - provides an overview of the API and a covers one of the samples within the API.&lt;/p&gt; &lt;p&gt;&lt;a title="Database Explorer API" href="blog/page/Database-Explorer-API-(beta).aspx"&gt;Database Explorer API&lt;/a&gt; - Provides more detailed information about the API including a class diagram. (work in progress)&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Download: &lt;a href="http://www.dotnetprofessional.com/blog/file.axd?file=Database+Explorer+-+Console+Sample.zip"&gt;Database Explorer - Console Sample.zip (39.42 kb)&lt;/a&gt;  &lt;p&gt;.&lt;/p&gt;&lt;div class="socialBookmarksContainer"&gt;&lt;a rel="nofollow" href="http://digg.com/submit/?url=http://dotnetprofessional.com/blog/post/2008/03/Database-Explorer-API-beta-released.aspx" target="_blank" title="Digg It!"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/digg_24.png" style="border: 0;" alt="Digg It!" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://www.dzone.com/links/add.html?url=http://dotnetprofessional.com/blog/post/2008/03/Database-Explorer-API-beta-released.aspx&amp;amp;title=Database Explorer API beta released" target="_blank" title="DZone It!"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/dzone_24.png" style="border: 0;" alt="DZone It!" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://www.stumbleupon.com/submit?url=http://dotnetprofessional.com/blog/post/2008/03/Database-Explorer-API-beta-released.aspx" target="_blank" title="StumbleUpon"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/stumbleupon_24.png" style="border: 0;" alt="StumbleUpon" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://technorati.com/ping?url=http://dotnetprofessional.com/blog/" target="_blank" title="Technorati"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/technorati_24.png" style="border: 0;" alt="Technorati" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://reddit.com/submit?url=http://dotnetprofessional.com/blog/post/2008/03/Database-Explorer-API-beta-released.aspx&amp;amp;title=Database Explorer API beta released" target="_blank" title="Reddit"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/reddit_24.png" style="border: 0;" alt="Reddit" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://del.icio.us/post?url=http://dotnetprofessional.com/blog/post/2008/03/Database-Explorer-API-beta-released.aspx&amp;amp;title=Database Explorer API beta released" target="_blank" title="Del.icio.us"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/delicious_24.png" style="border: 0;" alt="Del.icio.us" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://www.newsvine.com/_wine/save?u=http://dotnetprofessional.com/blog/post/2008/03/Database-Explorer-API-beta-released.aspx" target="_blank"title="NewsVine"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/newsvine_24.png" style="border: 0;" alt="NewsVine" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://furl.net" target="_blank" title="Furl"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/furl_24.png" style="border: 0;" alt="Furl" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://blinklist.com/submit/" target="_blank" title="BlinkList"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/blinklist_24.png" style="border: 0;" alt="BlinkList" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Dotnetprofessional/~4/339721348" height="1" width="1"/&gt;</description>
      <link>http://feeds.feedburner.com/~r/Dotnetprofessional/~3/339721348/post.aspx</link>
      <author>garrymc</author>
      <comments>http://dotnetprofessional.com/blog/post/2008/03/Database-Explorer-API-beta-released.aspx#comment</comments>
      <guid isPermaLink="false">http://dotnetprofessional.com/blog/post.aspx?id=80c6fcea-3004-4303-9915-62920ffb9870</guid>
      <pubDate>Mon, 17 Mar 2008 17:10:56 -0700</pubDate>
      <category>.NET 2.0</category>
      <category>Framework</category>
      <dc:publisher>garrymc</dc:publisher>
      <pingback:server>http://dotnetprofessional.com/blog/pingback.axd</pingback:server>
      <pingback:target>http://dotnetprofessional.com/blog/post.aspx?id=80c6fcea-3004-4303-9915-62920ffb9870</pingback:target>
      <slash:comments>1</slash:comments>
      <trackback:ping>http://dotnetprofessional.com/blog/trackback.axd?id=80c6fcea-3004-4303-9915-62920ffb9870</trackback:ping>
      <wfw:comment>http://dotnetprofessional.com/blog/post/2008/03/Database-Explorer-API-beta-released.aspx#comment</wfw:comment>
      <wfw:commentRss>http://dotnetprofessional.com/blog/syndication.axd?post=80c6fcea-3004-4303-9915-62920ffb9870</wfw:commentRss>
    <feedburner:origLink>http://dotnetprofessional.com/blog/post.aspx?id=80c6fcea-3004-4303-9915-62920ffb9870</feedburner:origLink></item>
    <item>
      <title>Did you forget something when you deployed your ASP.NET App?</title>
      <description>&lt;p&gt;While I don't normally get involved with deploying web applications (we normally have 'people' for that) however I did have to deploy the application you're using now. Which brings me to the blog post I recently found which discusses the top 10 best practices for ASP.NET which I've linked to on my &lt;a title="Toolbox with useful links and information." href="http://dotnetprofessional.com/blog/blog/pages/toolbox.aspx" target="_blank"&gt;toolbox&lt;/a&gt; page. The main one that concerned was of concern to me was forgetting to switch off debug mode. &lt;/p&gt; &lt;div class="csharpcode-wrapper"&gt; &lt;div class="csharpcode"&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:&lt;/span&gt; &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;system.web&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;   2:&lt;/span&gt;   &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;compilation&lt;/span&gt; &lt;span class="attr"&gt;debug&lt;/span&gt;&lt;span class="kwrd"&gt;="false"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre class="alt"&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;system.web&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="CopyToClipboard" style=""&gt;&lt;div&gt;&lt;a href="javascript:void(0);" onclick="CopyToClipboard_ViewPlain(copyToClipboard5f66ac4a0ee344cfbbb022ab1350502d_517);"&gt;View Plain&lt;/a&gt; | &lt;a href="javascript:void(0);" onclick="CopyToClipboard_Copy(copyToClipboard5f66ac4a0ee344cfbbb022ab1350502d_517);"&gt;Copy To Clipboard&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;
					&lt;script type="text/javascript"&gt;
						var copyToClipboard5f66ac4a0ee344cfbbb022ab1350502d_517 = CopyToClipboard_Strip('&amp;lt;system.web&amp;gt;   2:   &amp;lt;compilation debug="false" /&amp;gt;   3: &amp;lt;/system.web&amp;gt;');
					&lt;/script&gt;
&lt;p&gt;This setting appears to have a large impact on production web sites so I'd check out the detail in the &lt;a href="http://blogs.msdn.com/tess/archive/2006/04/13/575364.aspx" target="_blank"&gt;this post&lt;/a&gt; to get all the details. Also you might want to check the config files of the production apps you work on or blog if you host your own; lets just say we may need to update a few of ours!&lt;/p&gt;&lt;div class="socialBookmarksContainer"&gt;&lt;a rel="nofollow" href="http://digg.com/submit/?url=http://dotnetprofessional.com/blog/post/2008/03/Did-you-forget-something-when-you-deployed-your-ASPNET-App.aspx" target="_blank" title="Digg It!"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/digg_24.png" style="border: 0;" alt="Digg It!" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://www.dzone.com/links/add.html?url=http://dotnetprofessional.com/blog/post/2008/03/Did-you-forget-something-when-you-deployed-your-ASPNET-App.aspx&amp;amp;title=Did you forget something when you deployed your ASP.NET App?" target="_blank" title="DZone It!"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/dzone_24.png" style="border: 0;" alt="DZone It!" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://www.stumbleupon.com/submit?url=http://dotnetprofessional.com/blog/post/2008/03/Did-you-forget-something-when-you-deployed-your-ASPNET-App.aspx" target="_blank" title="StumbleUpon"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/stumbleupon_24.png" style="border: 0;" alt="StumbleUpon" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://technorati.com/ping?url=http://dotnetprofessional.com/blog/" target="_blank" title="Technorati"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/technorati_24.png" style="border: 0;" alt="Technorati" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://reddit.com/submit?url=http://dotnetprofessional.com/blog/post/2008/03/Did-you-forget-something-when-you-deployed-your-ASPNET-App.aspx&amp;amp;title=Did you forget something when you deployed your ASP.NET App?" target="_blank" title="Reddit"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/reddit_24.png" style="border: 0;" alt="Reddit" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://del.icio.us/post?url=http://dotnetprofessional.com/blog/post/2008/03/Did-you-forget-something-when-you-deployed-your-ASPNET-App.aspx&amp;amp;title=Did you forget something when you deployed your ASP.NET App?" target="_blank" title="Del.icio.us"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/delicious_24.png" style="border: 0;" alt="Del.icio.us" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://www.newsvine.com/_wine/save?u=http://dotnetprofessional.com/blog/post/2008/03/Did-you-forget-something-when-you-deployed-your-ASPNET-App.aspx" target="_blank"title="NewsVine"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/newsvine_24.png" style="border: 0;" alt="NewsVine" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://furl.net" target="_blank" title="Furl"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/furl_24.png" style="border: 0;" alt="Furl" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://blinklist.com/submit/" target="_blank" title="BlinkList"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/blinklist_24.png" style="border: 0;" alt="BlinkList" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Dotnetprofessional/~4/339721349" height="1" width="1"/&gt;</description>
      <link>http://feeds.feedburner.com/~r/Dotnetprofessional/~3/339721349/post.aspx</link>
      <author>garrymc</author>
      <comments>http://dotnetprofessional.com/blog/post/2008/03/Did-you-forget-something-when-you-deployed-your-ASPNET-App.aspx#comment</comments>
      <guid isPermaLink="false">http://dotnetprofessional.com/blog/post.aspx?id=c2eb8598-2ec5-43e6-aabc-5e25e26d0746</guid>
      <pubDate>Sat, 15 Mar 2008 04:54:28 -0700</pubDate>
      <category>.NET 1</category>
      <category>.NET 2.0</category>
      <category>.NET 3.5</category>
      <category>ASP.NET</category>
      <dc:publisher>garrymc</dc:publisher>
      <pingback:server>http://dotnetprofessional.com/blog/pingback.axd</pingback:server>
      <pingback:target>http://dotnetprofessional.com/blog/post.aspx?id=c2eb8598-2ec5-43e6-aabc-5e25e26d0746</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://dotnetprofessional.com/blog/trackback.axd?id=c2eb8598-2ec5-43e6-aabc-5e25e26d0746</trackback:ping>
      <wfw:comment>http://dotnetprofessional.com/blog/post/2008/03/Did-you-forget-something-when-you-deployed-your-ASPNET-App.aspx#comment</wfw:comment>
      <wfw:commentRss>http://dotnetprofessional.com/blog/syndication.axd?post=c2eb8598-2ec5-43e6-aabc-5e25e26d0746</wfw:commentRss>
    <feedburner:origLink>http://dotnetprofessional.com/blog/post.aspx?id=c2eb8598-2ec5-43e6-aabc-5e25e26d0746</feedburner:origLink></item>
    <item>
      <title>Visual Studio Extensibility (VSX) gets serious!</title>
      <description>&lt;p&gt;I went along to the &lt;a href="http://www.netda.net/" target="_blank"&gt;.NET developers association&lt;/a&gt; in Redmond on Monday where &lt;a href="http://blogs.msdn.com/klevy" target="_blank"&gt;Ken Levy&lt;/a&gt; demonstrated the extensibility tools of VS.NET 2008 (which also relates to VS 2005 to some extent). It seems that MS have decided to offer the VS 2008 shell license free! If you're anyone who's looking at providing third party tools (related or not to Visual Studio) and need a good IDE host, you've just saved yourself a bucket load of time. Also, it runs in two modes, integrated (merges with your instance of VS 2008) or isolated where it acts as its own (customisable too I was led to believe) IDE without the need for VS 2008. &lt;/p&gt;  &lt;p&gt;If you're not so inclined to use the VS Shell,&amp;#160; you may want to try adding your own custom extensions to VS to provide addition features MS haven't gotten around to yet. The API which used to be only available to partners (at a large cost - which is now free!) allows you to extend the IDE in just about any way you want. The VSX site provides links to numerous samples and they seem quite committed to building a large community around this technology, so I'd keep an eye on their &lt;a href="http://visualstudiogallery.com/" target="_blank"&gt;Visual Studio Gallery&lt;/a&gt; where the community will post their extensions.&lt;/p&gt;  &lt;p&gt;Other improvements seem to be in the area of DSLs (Domain Specific Languages) where they now provide DSL tools to build your own DSLs. This is an area I believe will become more important as people begin to realize that a lot of what we do is based on a known pattern, with customizations for a given problem.&lt;/p&gt;  &lt;p&gt;I'll be looking into how DSLs can be leveraged with the framework I'm currently developing that code gens your stored procs, entities and services. Anyway for those who are interested in learning more about these new tools I'd recommend you visit the following sites:   &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://msdn.com/vsx"&gt;http://msdn.com/vsx&lt;/a&gt; - The Visual Studio Extensibility home page&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/klevy"&gt;http://blogs.msdn.com/klevy&lt;/a&gt; - Ken Levy's blog&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;Also MS sponsored CoDe magazine for a special focus on VSX which allows you to download the full magazine which has a heap of VSX information. You can download the PDF &lt;a href="http://www.code-magazine.com/focus/" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Oh should mention that the demo's are quite impressive, take a look at the &lt;a href="http://blogs.msdn.com/vsxteam/archive/2007/12/15/AddOn-Studio-for-World-of-Warcraft-released.aspx" target="_blank"&gt;World of War Craft editor&lt;/a&gt; (with its own language) using the VS Shell.&lt;/p&gt;&lt;div class="socialBookmarksContainer"&gt;&lt;a rel="nofollow" href="http://digg.com/submit/?url=http://dotnetprofessional.com/blog/post/2008/03/Visual-Studio-Extensibility-(VSX)-gets-serious!.aspx" target="_blank" title="Digg It!"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/digg_24.png" style="border: 0;" alt="Digg It!" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://www.dzone.com/links/add.html?url=http://dotnetprofessional.com/blog/post/2008/03/Visual-Studio-Extensibility-(VSX)-gets-serious!.aspx&amp;amp;title=Visual Studio Extensibility (VSX) gets serious!" target="_blank" title="DZone It!"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/dzone_24.png" style="border: 0;" alt="DZone It!" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://www.stumbleupon.com/submit?url=http://dotnetprofessional.com/blog/post/2008/03/Visual-Studio-Extensibility-(VSX)-gets-serious!.aspx" target="_blank" title="StumbleUpon"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/stumbleupon_24.png" style="border: 0;" alt="StumbleUpon" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://technorati.com/ping?url=http://dotnetprofessional.com/blog/" target="_blank" title="Technorati"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/technorati_24.png" style="border: 0;" alt="Technorati" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://reddit.com/submit?url=http://dotnetprofessional.com/blog/post/2008/03/Visual-Studio-Extensibility-(VSX)-gets-serious!.aspx&amp;amp;title=Visual Studio Extensibility (VSX) gets serious!" target="_blank" title="Reddit"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/reddit_24.png" style="border: 0;" alt="Reddit" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://del.icio.us/post?url=http://dotnetprofessional.com/blog/post/2008/03/Visual-Studio-Extensibility-(VSX)-gets-serious!.aspx&amp;amp;title=Visual Studio Extensibility (VSX) gets serious!" target="_blank" title="Del.icio.us"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/delicious_24.png" style="border: 0;" alt="Del.icio.us" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://www.newsvine.com/_wine/save?u=http://dotnetprofessional.com/blog/post/2008/03/Visual-Studio-Extensibility-(VSX)-gets-serious!.aspx" target="_blank"title="NewsVine"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/newsvine_24.png" style="border: 0;" alt="NewsVine" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://furl.net" target="_blank" title="Furl"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/furl_24.png" style="border: 0;" alt="Furl" /&gt;&lt;/a&gt;&lt;a rel="nofollow" href="http://blinklist.com/submit/" target="_blank" title="BlinkList"&gt;&lt;img src="/blog/themes\BrightSide/socialbookmarks/square/blinklist_24.png" style="border: 0;" alt="BlinkList" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Dotnetprofessional/~4/339721350" height="1" width="1"/&gt;</description>
      <link>http://feeds.feedburner.com/~r/Dotnetprofessional/~3/339721350/post.aspx</link>
      <author>garrymc</author>
      <comments>http://dotnetprofessional.com/blog/post/2008/03/Visual-Studio-Extensibility-(VSX)-gets-serious!.aspx#comment</comments>
      <guid isPermaLink="false">http://dotnetprofessional.com/blog/post.aspx?id=5fd5325c-c408-407e-9304-8d43e08b4383</guid>
      <pubDate>Thu, 13 Mar 2008 02:51:39 -0700</pubDate>
      <category>.NET 3.5</category>
      <category>Visual Studio</category>
      <dc:publisher>garrymc</dc:publisher>
      <pingback:server>http://dotnetprofessional.com/blog/pingback.axd</pingback:server>
      <pingback:target>http://dotnetprofessional.com/blog/post.aspx?id=5fd5325c-c408-407e-9304-8d43e08b4383</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://dotnetprofessional.com/blog/trackback.axd?id=5fd5325c-c408-407e-9304-8d43e08b4383</trackback:ping>
      <wfw:comment>http://dotnetprofessional.com/blog/post/2008/03/Visual-Studio-Extensibility-(VSX)-gets-serious!.aspx#comment</wfw:comment>
      <wfw:commentRss>http://dotnetprofessional.com/blog/syndication.axd?post=5fd5325c-c408-407e-9304-8d43e08b4383</wfw:commentRss>
    <feedburner:origLink>http://dotnetprofessional.com/blog/post.aspx?id=5fd5325c-c408-407e-9304-8d43e08b4383</feedburner:origLink></item>
    <item>
      <title>ASP.NET Dynamic Controls &amp;amp; State Management</title>
      <description>&lt;blockquote&gt;   &lt;p&gt;This article was originally published in the April 2003 issue of Visual Studio Magazine. Their online version has been archived, so it has been reproduced here. The articles code requires updating for .NET 2.0 which will be the subject of a future post.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;ASP.NET has brought about a huge change in how we as developers think about designing a web site. We all know that ASP.NET now gives us the opportunity to create reusable custom controls which we can drag and drop onto our pages, which can even remember the information entered between postbacks, using the viewstate mechanism built into ASP.NET. This has proven to be a huge advantage in designing our pages, by allowing us to bring our more traditional programming model to the Web for the first time. ASP.NET also allows us to add these same controls dynamically at runtime. &lt;/p&gt;  &lt;p&gt;The sample project which we will create is a relatively simple one, which should clearly demonstrate all the issues that you will face when trying to create dynamic controls yourself. In general Microsoft has done a good job with their architecture and made it really quite straightforward. However, there are circumstances where things do start to get somewhat more interesting, and we will tackle this area in detail so that you will be armed with all the knowledge you need to tackle any dynamic control issue.&lt;/p&gt;  &lt;h2&gt;Why Use Dynamic Controls?&lt;/h2&gt;  &lt;p&gt;The ability to add controls at runtime gives us the ability to create some very sophisticated web sites. We could for example have the home page render completely differently based on the users profile. We could also dynamically load the modules or controls that the user wanted so that the experience would be unique for each user. This is a particularly powerful technique if you need to change branding of your site dynamically. However, this is not the only use, if you were to create a Wizard, then you would want to load different screens based on the previous selection.&lt;/p&gt;  &lt;h2&gt;Creating our first Dynamic Control Page&lt;/h2&gt;  &lt;p&gt;The good news is that ASP.NET allows us to create dynamic controls very easily, well it does in part but I&amp;#8217;ll come to that later. To dynamically create a control at runtime all we need to do is use the following line of code. &lt;/p&gt;  &lt;div class="csharpcode-wrapper"&gt;   &lt;div class="csharpcode"&gt;     &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:&lt;/span&gt; Me.Controls.Add(Page.LoadControl(&amp;#8220;~/MyControl.ascx&amp;#8221;)&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;&lt;div class="CopyToClipboard" style=""&gt;&lt;div&gt;&lt;a href="javascript:void(0);" onclick="CopyToClipboard_ViewPlain(copyToClipboard909103a2be9c47b59a3c913b984021c2_2319);"&gt;View Plain&lt;/a&gt; | &lt;a href="javascript:void(0);" onclick="CopyToClipboard_Copy(copyToClipboard909103a2be9c47b59a3c913b984021c2_2319);"&gt;Copy To Clipboard&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;
					&lt;script type="text/javascript"&gt;
						var copyToClipboard909103a2be9c47b59a3c913b984021c2_2319 = CopyToClipboard_Strip('Me.Controls.Add(Page.LoadControl(&amp;#8220;~/MyControl.ascx&amp;#8221;)');
					&lt;/script&gt;

&lt;p&gt;You should note however that the control to be loaded must be the fully qualified name otherwise you may get a file not found error. A good tip is to use the &amp;#8216;~&amp;#8217; tilde at the beginning as it is a special character which represents the root of the web application, when used with Server side controls.&lt;/p&gt;

&lt;p&gt;This is the most basic way to display a dynamic control. In the example above we just added the control to the pages control collection. However&lt;a title="Figure 1" href="http://dotnetprofessional.com/blog/image.axd?picture=WindowsLiveWriter/ASP.NETDynamicControlsStateManagement_13B13/Figure%201%20-%20Project%20Structure_4.jpg" rel="lightbox"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; margin: 10px 0px 10px 10px; border-right-width: 0px" height="207" alt="Figure 1 - Project Structure" src="http://dotnetprofessional.com/blog/image.axd?picture=WindowsLiveWriter/ASP.NETDynamicControlsStateManagement_13B13/Figure%201%20-%20Project%20Structure_thumb_1.jpg" width="244" align="right" border="0" /&gt;&lt;/a&gt;, you can do the same thing for any container control such as a Panel or Placeholder control. In most cases you will probably want to use a Panel or Placeholder as it will allow easier positioning on the page. This is precisely what we use in our sample project, see &lt;strong&gt;Figure 1&lt;/strong&gt;. As you can see we have arranged three Panel controls on the page to represent a Title, Menu/Login and Content area. This should be a familiar web design to most of you. As you can see there isn&amp;#8217;t any real visual content yet, as we will be adding this content dynamically each time the page loads. We will be creating several simple User Controls to insert into the panel areas which we can easily create in VS.NET. It should be kept in mind that these controls can comprise any number of ASP.NET Controls. To demonstrate the use of dynamic controls we will create a series of steps or screens to guide a potential user of our site through registration. To keep it simple we will assume that anyone who isn&amp;#8217;t registered will want to be and make our registration page our home page. You will I trust not replicate this in your site!&lt;/p&gt;

&lt;p&gt;Due to the time it would take to describe exactly what I&amp;#8217;ve built, I&amp;#8217;d prefer to mention the &amp;#8216;interesting&amp;#8217; points of code and ask that you download the sample project which contains all the code. For instructions on how to make use of these samples check out the sidebar.&lt;/p&gt;

&lt;h2&gt;Creating a Wizard Control&lt;/h2&gt;

&lt;p&gt;The sample consists of the following User Controls&lt;/p&gt;

&lt;table cellspacing="0" cellpadding="2" width="398" border="1"&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td valign="top" width="202"&gt;Banner.ascx&lt;/td&gt;

      &lt;td valign="top" width="194"&gt;Banner no advertising&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="top" width="204"&gt;Banner_Advertising.ascx&lt;/td&gt;

      &lt;td valign="top" width="193"&gt;Banner with advertising&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="top" width="205"&gt;Wizard.ascx&lt;/td&gt;

      &lt;td valign="top" width="192"&gt;Container for each step&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="top" width="206"&gt;Wizard_Step1.ascx&lt;/td&gt;

      &lt;td valign="top" width="192"&gt;Get Username &amp;amp; Password&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="top" width="206"&gt;Wizard_Step2.ascx&lt;/td&gt;

      &lt;td valign="top" width="192"&gt;Get personal Details&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="top" width="206"&gt;Wizard_Step3.ascx&lt;/td&gt;

      &lt;td valign="top" width="192"&gt;Confirm Data Collected&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="top" width="206"&gt;Login.ascx&lt;/td&gt;

      &lt;td valign="top" width="192"&gt;Allow user to login&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="top" width="206"&gt;Menu.ascx&lt;/td&gt;

      &lt;td valign="top" width="192"&gt;Sample of a menu&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;What we want to do is create a Wizard interface that we can then dynamically load our steps into at runtime. This has several advantages, namely that it keeps the code for each step simple and also allows you to change the Wizards look and feel anytime without going back to the i&lt;a title="Figure 2" href="http://dotnetprofessional.com/blog/image.axd?picture=WindowsLiveWriter/ASP.NETDynamicControlsStateManagement_13B13/Figure%202%20-%20Wizard%20Interface_2.jpg" rel="lightbox"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; margin: 10px 0px 10px 10px; border-right-width: 0px" height="158" alt="Figure 2 - Wizard Interface" src="http://dotnetprofessional.com/blog/image.axd?picture=WindowsLiveWriter/ASP.NETDynamicControlsStateManagement_13B13/Figure%202%20-%20Wizard%20Interface_thumb.jpg" width="244" align="right" border="0" /&gt;&lt;/a&gt;ndividual steps. &lt;strong&gt;Figure 2&lt;/strong&gt; shows the structure of our Wizard interface, the other controls such as the Banner are simply text written onto the control, one having some advertising the other not. All of these controls will be dynamically loaded into the Template shown in &lt;strong&gt;Figure 1&lt;/strong&gt; as previously discussed. The UseControl in the middle of the Wizard will be discussed later in the article. &lt;/p&gt;

&lt;p&gt;Looking at the Wizard template you&amp;#8217;ll notice that I&amp;#8217;ve decided to keep the traditional Wizard style interface and have a Title and Description for each step. These details will be taken from each step as it is loaded into the control. The question then arises how do we achieve this? The best way is to make use of Interfaces. As we know an Interface allows us to create a type of contract that each object that implements it must adhere to. Then when we want to reference those objects, we can be guaranteed that if they have implemented the interface that it will have at least those properties and methods defined by the interface. Another great advantage of using interfaces is that it allows us to use early binding in our code, and therefore reduces potential errors. So I&amp;#8217;ve created the IWizard interface which has the following signature (a signature is a common term to describe the properties and methods that make up an interface). 
  &lt;br /&gt;

  &lt;br /&gt;&lt;/p&gt;

&lt;div class="csharpcode-wrapper"&gt;
  &lt;div class="csharpcode"&gt;
    &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:&lt;/span&gt; &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Interface&lt;/span&gt; IWizard&lt;/pre&gt;

    &lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;   2:&lt;/span&gt;     &lt;span class="kwrd"&gt;ReadOnly&lt;/span&gt; &lt;span class="kwrd"&gt;Property&lt;/span&gt; Title() &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;&lt;/pre&gt;

    &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:&lt;/span&gt;     &lt;span class="kwrd"&gt;ReadOnly&lt;/span&gt; &lt;span class="kwrd"&gt;Property&lt;/span&gt; Description() &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;&lt;/pre&gt;

    &lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;   4:&lt;/span&gt;     &lt;span class="kwrd"&gt;ReadOnly&lt;/span&gt; &lt;span class="kwrd"&gt;Property&lt;/span&gt; NextStep() &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;&lt;/pre&gt;

    &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:&lt;/span&gt;     &lt;span class="kwrd"&gt;ReadOnly&lt;/span&gt; &lt;span class="kwrd"&gt;Property&lt;/span&gt; PreviousStep() &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;&lt;/pre&gt;

    &lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;   6:&lt;/span&gt; &lt;span class="kwrd"&gt;End&lt;/span&gt; Interface&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;&lt;div class="CopyToClipboard" style=""&gt;&lt;div&gt;&lt;a href="javascript:void(0);" onclick="CopyToClipboard_ViewPlain(copyToClipboard909103a2be9c47b59a3c913b984021c2_9116);"&gt;View Plain&lt;/a&gt; | &lt;a href="javascript:void(0);" onclick="CopyToClipboard_Copy(copyToClipboard909103a2be9c47b59a3c913b984021c2_9116);"&gt;Copy To Clipboard&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;
					&lt;script type="text/javascript"&gt;
						var copyToClipboard909103a2be9c47b59a3c913b984021c2_9116 = CopyToClipboard_Strip('Public Interface IWizard\r\n    ReadOnly Property Title() As String\r\n    ReadOnly Property Description() As String\r\n    ReadOnly Property NextStep() As String\r\n    ReadOnly Property PreviousStep() As String\r\nEnd Interface');
					&lt;/script&gt;

&lt;p&gt;I have added a few extras to help us know what the next and previous steps in the wizard are. This will help our container control (ie Wizard.ascx) know which control to load next and which buttons should be enabled etc. As this is directly related to the Wizard UI I&amp;#8217;ve put this Interface code in the Wizard.ascx file. You can see how all this code has been implemented by looking at the code behind file for the Wizard.&lt;/p&gt;

&lt;p&gt;Now that we have defined our Wizard interface we need to ensure that each step implements it. To see how this is done check &lt;strong&gt;Listing 1&lt;/strong&gt;. A thing to note about this code is how we determine the next step. In essence we check that the information entered on the screen for that step is valid. If it is then return the next step, if not then return the current step.&lt;/p&gt;

&lt;p&gt;Now that we have coded all the steps to incorporate our IWizard interface and have coded the Wizard itself, its time to see if it works. When we run our first sample application (Example1.aspx), we get a screen that should look like that of &lt;strong&gt;Figure 3&lt;/strong&gt;. Here you can see that we have loaded three controls dynamically into the Template (see &lt;strong&gt;Listing 2&lt;/strong&gt;). In this case, as the user has not logged in, they are presented with the ability to register. To keep things simple you can see that the code merely checks a QueryString parameter for a value of &amp;#8216;True&amp;#8217;.&lt;/p&gt;

&lt;h2&gt;Maintaining State between PostBacks&lt;/h2&gt;

&lt;p&gt;When we enter our details and press next we notice that we get a rather unexpected result, none of the controls we added are still there. The reason for this is because of the way we normally code our ASP.NET Form_Load events. Normally we would do the following as is the case in our first example (see &lt;strong&gt;Listing 2&lt;/strong&gt;).&lt;/p&gt;

&lt;div class="csharpcode-wrapper"&gt;
  &lt;div class="csharpcode"&gt;
    &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt; &lt;span class="kwrd"&gt;Not&lt;/span&gt; &lt;span class="kwrd"&gt;Me&lt;/span&gt;.IsPostBack &lt;span class="kwrd"&gt;Then&lt;/span&gt;&lt;/pre&gt;

    &lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;   2:&lt;/span&gt;     &amp;#8230;&lt;/pre&gt;

    &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:&lt;/span&gt; &lt;span class="kwrd"&gt;End&lt;/span&gt; If&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;&lt;div class="CopyToClipboard" style=""&gt;&lt;div&gt;&lt;a href="javascript:void(0);" onclick="CopyToClipboard_ViewPlain(copyToClipboard909103a2be9c47b59a3c913b984021c2_12821);"&gt;View Plain&lt;/a&gt; | &lt;a href="javascript:void(0);" onclick="CopyToClipboard_Copy(copyToClipboard909103a2be9c47b59a3c913b984021c2_12821);"&gt;Copy To Clipboard&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;
					&lt;script type="text/javascript"&gt;
						var copyToClipboard909103a2be9c47b59a3c913b984021c2_12821 = CopyToClipboard_Strip('If Not Me.IsPostBack Then\r\n    &amp;#8230;\r\nEnd If');
					&lt;/script&gt;

&lt;p&gt;If we hadn&amp;#8217;t created these controls dynamically this style of coding would be both fine and preferable, as it means we don&amp;#8217;t have to do any extra work. However, this doesn&amp;#8217;t work because despite how much Microsoft have done for us, we are still living in a stateless environment, and to that end if you create something at runtime, ASP.NET won&amp;#8217;t keep track of it for you. You will need to do that for yourself. This means you can&amp;#8217;t make use of this feature as you must always recreate the controls each time. &lt;/p&gt;

&lt;div class="csharpcode-wrapper"&gt;
  &lt;div class="csharpcode"&gt;
    &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   &lt;strong&gt;Listing 1 &amp;#8211; Wizard_Step1.ascx &lt;/strong&gt;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:&lt;/span&gt; &lt;span class="preproc"&gt;#Region&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;IWizard Interface&amp;quot;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;   2:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:&lt;/span&gt;     &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;ReadOnly&lt;/span&gt; &lt;span class="kwrd"&gt;Property&lt;/span&gt; Title() _&lt;/pre&gt;

    &lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;   4:&lt;/span&gt;         &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt; &lt;span class="kwrd"&gt;Implements&lt;/span&gt; IWizard.Title&lt;/pre&gt;

    &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:&lt;/span&gt;         &lt;span class="kwrd"&gt;Get&lt;/span&gt;&lt;/pre&gt;

    &lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;   6:&lt;/span&gt;             &lt;span class="kwrd"&gt;Return&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;User Registration&amp;quot;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:&lt;/span&gt;         &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Get&lt;/span&gt;&lt;/pre&gt;

    &lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;   8:&lt;/span&gt;     &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Property&lt;/span&gt;&lt;/pre&gt;

    &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  10:&lt;/span&gt;     &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;ReadOnly&lt;/span&gt; &lt;span class="kwrd"&gt;Property&lt;/span&gt; Description() &lt;span class="kwrd"&gt;As&lt;/span&gt; _&lt;/pre&gt;

    &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:&lt;/span&gt;             &lt;span class="kwrd"&gt;String&lt;/span&gt; &lt;span class="kwrd"&gt;Implements&lt;/span&gt; IWizard.Description&lt;/pre&gt;

    &lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  12:&lt;/span&gt;         &lt;span class="kwrd"&gt;Get&lt;/span&gt;&lt;/pre&gt;

    &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:&lt;/span&gt;             &lt;span class="kwrd"&gt;Return&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;Please enter the Username and Password you wish to use on our site.&amp;quot;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  14:&lt;/span&gt;         &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Get&lt;/span&gt;&lt;/pre&gt;

    &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:&lt;/span&gt;     &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Property&lt;/span&gt;&lt;/pre&gt;

    &lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  16:&lt;/span&gt;     &lt;/pre&gt;

    &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  17:&lt;/span&gt;     &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;ReadOnly&lt;/span&gt; &lt;span class="kwrd"&gt;Property&lt;/span&gt; NextStep() &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt; _&lt;/pre&gt;

    &lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  18:&lt;/span&gt;             &lt;span class="kwrd"&gt;Implements&lt;/span&gt; IWizard.NextStep&lt;/pre&gt;

    &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  19:&lt;/span&gt;         &lt;span class="kwrd"&gt;Get&lt;/span&gt;&lt;/pre&gt;

    &lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  20:&lt;/span&gt;             &lt;span class="kwrd"&gt;If&lt;/span&gt; &lt;span class="kwrd"&gt;Me&lt;/span&gt;.txtName.Text.Length &amp;gt; 0 &lt;span class="kwrd"&gt;AndAlso&lt;/span&gt; _&lt;/pre&gt;

    &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  21:&lt;/span&gt;                     &lt;span class="kwrd"&gt;Me&lt;/span&gt;.txtPassword.Text.Length &amp;gt; 0 &lt;span class="kwrd"&gt;Then&lt;/span&gt;&lt;/pre&gt;

    &lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  22:&lt;/span&gt;                 &lt;span class="kwrd"&gt;Return&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;~/Wizard_Step2.ascx&amp;quot;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  23:&lt;/span&gt;             &lt;span class="kwrd"&gt;Else&lt;/span&gt;&lt;/pre&gt;

    &lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  24:&lt;/span&gt;                 &lt;span class="kwrd"&gt;Return&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;~/Wizard_Step1.ascx&amp;quot;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  25:&lt;/span&gt;             &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;&lt;/pre&gt;

    &lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  26:&lt;/span&gt;         &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Get&lt;/span&gt;&lt;/pre&gt;

    &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  27:&lt;/span&gt;     &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Property&lt;/span&gt;&lt;/pre&gt;

    &lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  28:&lt;/span&gt;     &lt;/pre&gt;

    &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  29:&lt;/span&gt;     &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;ReadOnly&lt;/span&gt; &lt;span class="kwrd"&gt;Property&lt;/span&gt; PreviousStep() &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt; _&lt;/pre&gt;

    &lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  30:&lt;/span&gt;             &lt;span class="kwrd"&gt;Implements&lt;/span&gt; IWizard.PreviousStep&lt;/pre&gt;

    &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  31:&lt;/span&gt;         &lt;span class="kwrd"&gt;Get&lt;/span&gt;&lt;/pre&gt;

    &lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  32:&lt;/span&gt;             &lt;span class="kwrd"&gt;Return&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;Start&amp;quot;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  33:&lt;/span&gt;         &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Get&lt;/span&gt;&lt;/pre&gt;

    &lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  34:&lt;/span&gt;     &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Property&lt;/span&gt;&lt;/pre&gt;

    &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  35:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  36:&lt;/span&gt; &lt;span class="preproc"&gt;#End Region&lt;/span&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;&lt;div class="CopyToClipboard" style=""&gt;&lt;div&gt;&lt;a href="javascript:void(0);" onclick="CopyToClipboard_ViewPlain(copyToClipboard909103a2be9c47b59a3c913b984021c2_14346);"&gt;View Plain&lt;/a&gt; | &lt;a href="javascript:void(0);" onclick="CopyToClipboard_Copy(copyToClipboard909103a2be9c47b59a3c913b984021c2_14346);"&gt;Copy To Clipboard&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;
					&lt;script type="text/javascript"&gt;
						var copyToClipboard909103a2be9c47b59a3c913b984021c2_14346 = CopyToClipboard_Strip('   Listing 1 &amp;#8211; Wizard_Step1.ascx \r\n#Region &amp;quot;IWizard Interface&amp;quot;\r\n\r\n    Public ReadOnly Property Title() _\r\n        As String Implements IWizard.Title\r\n        Get\r\n            Return &amp;quot;User Registration&amp;quot;\r\n        End Get\r\n    End Property\r\n\r\n    Public ReadOnly Property Description() As _\r\n            String Implements IWizard.Description\r\n        Get\r\n            Return &amp;quot;Please enter the Username and Password you wish to use on our site.&amp;quot;\r\n        End Get\r\n    End Property\r\n    \r\n    Public ReadOnly Property NextStep() As String _\r\n            Implements IWizard.NextStep\r\n        Get\r\n            If Me.txtName.Text.Length &amp;gt; 0 AndAlso _\r\n                    Me.txtPassword.Text.Length &amp;gt; 0 Then\r\n                Return &amp;quot;~/Wizard_Step2.ascx&amp;quot;\r\n            Else\r\n                Return &amp;quot;~/Wizard_Step1.ascx&amp;quot;\r\n            End If\r\n        End Get\r\n    End Property\r\n    \r\n    Public ReadOnly Property PreviousStep() As String _\r\n            Implements IWizard.PreviousStep\r\n        Get\r\n            Return &amp;quot;Start&amp;quot;\r\n        End Get\r\n    End Property\r\n\r\n#End Region');
					&lt;/script&gt;

&lt;p&gt;We could overcome this by removing the IF condition and it would fix our initial problem by recreating the controls during each postback, however there are still many issues that need to be resolved such as the following.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;We need to keep track of the last control, load it and have its events fire before we remove it to replace it with the control for the next step. &lt;/li&gt;

  &lt;li&gt;Replace current control with the next one. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This process can start to become rather complicated and it would be much better if we were able to wrap this complexity up into a user control. This is exactly what we will be tackling next. &lt;/p&gt;

&lt;h2&gt;Creating a Dynamic Control Host Control&lt;/h2&gt;

&lt;p&gt;To make our coding life easier and to solve the problems associated with creating dynamic controls, we can create a control which handles all the more complex tasks for us. This then leaves us with a simple object model to program against. This is what we will be using in Example 2, and it makes what would otherwise be a complicated task easy.&lt;/p&gt;

&lt;p&gt;The amount of code required for our control isn&amp;#8217;t particularly large, but the concepts behind it all can be a bit confusing. I will try to explain the code presented in &lt;strong&gt;Listing 3&lt;/strong&gt;, and point out the issues as we go along. &lt;/p&gt;

&lt;div class="csharpcode-wrapper"&gt;
  &lt;div class="csharpcode"&gt;
    &lt;pre class="alt"&gt;   &lt;strong&gt;Listing 2 &amp;#8211; Load Event of Example1.aspx&lt;/strong&gt;&lt;/pre&gt;

    &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:&lt;/span&gt; &lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; Page_Load(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; sender &lt;span class="kwrd"&gt;As&lt;/span&gt; System.&lt;span class="kwrd"&gt;Object&lt;/span&gt;, _&lt;/pre&gt;

    &lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;   2:&lt;/span&gt;         &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; e &lt;span class="kwrd"&gt;As&lt;/span&gt; System.EventArgs) &lt;span class="kwrd"&gt;Handles&lt;/span&gt; &lt;span class="kwrd"&gt;MyBase&lt;/span&gt;.Load&lt;/pre&gt;

    &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:&lt;/span&gt;     &lt;span class="rem"&gt;'Put user code to initialise the page here&lt;/span&gt;&lt;/pre&gt;

    &lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;   4:&lt;/span&gt;     &lt;span class="rem"&gt;' Create the page based on the user who has entered&lt;/span&gt;&lt;/pre&gt;

    &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:&lt;/span&gt;     &lt;span class="kwrd"&gt;If&lt;/span&gt; &lt;span class="kwrd"&gt;Not&lt;/span&gt; &lt;span class="kwrd"&gt;Me&lt;/span&gt;.IsPostBack &lt;span class="kwrd"&gt;Then&lt;/span&gt;&lt;/pre&gt;

    &lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;   6:&lt;/span&gt;         &lt;span class="kwrd"&gt;If&lt;/span&gt; Request.QueryString(&lt;span class="str"&gt;&amp;quot;Registered&amp;quot;&lt;/span&gt;) = &lt;span class="str"&gt;&amp;quot;True&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;Then&lt;/span&gt;&lt;/pre&gt;

    &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:&lt;/span&gt;             &lt;span class="rem"&gt;' Top security here, you might want to do better&lt;/span&gt;&lt;/pre&gt;

    &lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;   8:&lt;/span&gt;             &amp;#8216; authentication&lt;/pre&gt;

    &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:&lt;/span&gt;             &lt;span class="kwrd"&gt;Me&lt;/span&gt;.pnlBanner.Controls. _&lt;/pre&gt;

    &lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  10:&lt;/span&gt;                 Add(Page.LoadControl(&lt;span class="str"&gt;&amp;quot;~/Banner.ascx&amp;quot;&lt;/span&gt;))&lt;/pre&gt;

    &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:&lt;/span&gt;             &lt;span class="kwrd"&gt;Me&lt;/span&gt;.pnlMenu.Controls. _&lt;/pre&gt;

    &lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  12:&lt;/span&gt;                 Add(Page.LoadControl(&lt;span class="str"&gt;&amp;quot;~/menu.ascx&amp;quot;&lt;/span&gt;))&lt;/pre&gt;

    &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:&lt;/span&gt;         &lt;span class="kwrd"&gt;Else&lt;/span&gt;&lt;/pre&gt;

    &lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  14:&lt;/span&gt;             &lt;span class="kwrd"&gt;Me&lt;/span&gt;.pnlBanner.Controls. _&lt;/pre&gt;

    &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:&lt;/span&gt;                 Add(Page.LoadControl(&lt;span class="str"&gt;&amp;quot;~/Banner_Advertising.ascx&amp;quot;&lt;/span&gt;))&lt;/pre&gt;

    &lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  16:&lt;/span&gt;             &lt;span class="kwrd"&gt;Me&lt;/span&gt;.pnlMenu.Controls.Add(Page.LoadControl(&lt;span class="str"&gt;&amp;quot;~/Login.ascx&amp;quot;&lt;/span&gt;))&lt;/pre&gt;

    &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  17:&lt;/span&gt;             &lt;span class="kwrd"&gt;Me&lt;/span&gt;.pnlContent.Controls. _&lt;/pre&gt;

    &lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  18:&lt;/span&gt;                 Add(Page.LoadControl(&lt;span class="str"&gt;&amp;quot;~/Wizard.ascx&amp;quot;&lt;/span&gt;))&lt;/pre&gt;

    &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  19:&lt;/span&gt;         &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;&lt;/pre&gt;

    &lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;  20:&lt;/span&gt;     &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;&lt;/pre&gt;

    &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  21:&lt;/span&gt; &lt;span class="kwrd"&gt;End&lt;/span&gt; Sub&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;&lt;div class="CopyToClipboard" style=""&gt;&lt;div&gt;&lt;a href="javascript:void(0);" onclick="CopyToClipboard_ViewPlain(copyToClipboard909103a2be9c47b59a3c913b984021c2_22627);"&gt;View Plain&lt;/a&gt; | &lt;a href="javascript:void(0);" onclick="CopyToClipboard_Copy(copyToClipboard909103a2be9c47b59a3c913b984021c2_22627);"&gt;Copy To Clipboard&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;
					&lt;script type="text/javascript"&gt;
						var copyToClipboard909103a2be9c47b59a3c913b984021c2_22627 = CopyToClipboard_Strip('   Listing 2 &amp;#8211; Load Event of Example1.aspx\r\nPrivate Sub Page_Load(ByVal sender As System.Object, _\r\n        ByVal e As System.EventArgs) Handles MyBase.Load\r\n    \'Put user code to initialise the page here\r\n    \' Create the page based on the user who has entered\r\n    If Not Me.IsPostBack Then\r\n        If Request.QueryString(&amp;quot;Registered&amp;quot;) = &amp;quot;True&amp;quot; Then\r\n            \' Top security here, you might want to do better\r\n            &amp;#8216; authentication\r\n            Me.pnlBanner.Controls. _\r\n                Add(Page.LoadControl(&amp;quot;~/Banner.ascx&amp;quot;))\r\n            Me.pnlMenu.Controls. _\r\n                Add(Page.LoadControl(&amp;quot;~/menu.ascx&amp;quot;))\r\n        Else\r\n            Me.pn