<?xml version="1.0" encoding="UTF-8"?>
<!-- generator="wordpress/2.3.3" --><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Oleg Sych</title>
	<link>http://www.olegsych.com</link>
	<description>Me.Write(code)</description>
	<pubDate>Tue, 14 Jul 2009 18:16:06 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.3.3</generator>
	<language>en</language>
			<creativeCommons:license>http://creativecommons.org/licenses/by-sa/2.5/</creativeCommons:license><image><link>http://creativecommons.org/licenses/by-sa/2.5/</link><url>http://creativecommons.org/images/public/somerights20.gif</url><title>Some Rights Reserved</title></image><xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item>
		<title>MVP Award</title>
		<link>http://feedproxy.google.com/~r/olegsych/~3/E0hwmEgwkWA/</link>
		<comments>http://www.olegsych.com/2009/07/mvp-award/#comments</comments>
		<pubDate>Mon, 06 Jul 2009 10:50:54 +0000</pubDate>
		<dc:creator>Oleg Sych</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.olegsych.com/2009/07/mvp-award/</guid>
		<description><![CDATA[I am truly honored to receive the Most Valued Professional (MVP) award from Microsoft. It is both humbling and immensely satisfying to be recognized by this great company. I find it remarkable that a company of this size is so passionate and consistent about supporting its user community and partners. 
Of course the company can [...]]]></description>
			<content:encoded><![CDATA[<p>I am truly honored to receive the <a href="https://mvp.support.microsoft.com/profile/Oleg.Sych">Most Valued Professional (MVP) award from Microsoft</a>. It is both humbling and immensely satisfying to be recognized by this great company. I find it remarkable that a company of this size is so passionate and consistent about supporting its user community and partners. </p>
<p>Of course the company can only be as great as the people working there make it. I would like to thank these great people working at Microsoft for the inspiration and support: <a href="http://www.devfish.net">Joe Healy</a>, <a href="http://blogs.msdn.com/garethj">Gareth Jones</a>, <a href="http://jimblizzard.wordpress.com">Jim Blizzard</a>, <a href="http://blogs.msdn.com/jmprieur">Jean-Mark Prieur</a>, <a href="http://blogs.msdn.com/jbarnes">Jeff Barnes</a>, <a href="http://www.hanselman.com/">Scott Hanselman</a>, <a href="http://blog.wekeroad.com">Rob Caron</a>, <a href="http://blogs.msdn.com/timfis">Tim Fischer</a>. Regardless of whether &quot;community work&quot; is in your job description or not, you helped me in one way or another and I am grateful for that. </p>
<p>This award also would not be possible without the prominent members of the Microsoft community: <a href="http://geekswithblogs.net/sdorman">Scott Doorman</a>, <a href="http://www.vbnetexpert.com">Stan Schultes</a>, <a href="http://davesblog.computerways.com">Dave Noderer</a>, <a href="http://www.swfldev.net">John Dunagan</a>, <a href="http://www.goisc.com">Steve Lane</a>, <a href="http://www.shawnweisfeld.com">Shawn Weisfeld</a>, <a href="http://www.cfdotnet.org/Blog/tabid/65/Default.aspx">Roy Lawson</a> and many many more. So much goes on behind the scenes to keep the user groups going and prepare the code camps. Without your work the development community in Florida wouldn’t be as great as it is today.</p>
<p>And last, but not least, I want to thank my friends and colleagues at <a href="http://www.catapultsystems.com/">Catapult</a>: <a href="http://www.jeffreylodell.com/">Jeff Odell</a>, <a href="http://www.randypatterson.com">Randy Patterson</a>, Terri Burmeister, James McAuliffe. Whether it was buying pizza for a user group meeting, discussing technical issues after hours or having a beer after work, your encouragement and support is very much appreciated. </p>
<p>Sincerely,   <br />Oleg</p>
<p>&copy;2009 <a href="http://www.olegsych.com">Oleg Sych</a>. All Rights Reserved.</p>.<img src="http://feeds.feedburner.com/~r/olegsych/~4/E0hwmEgwkWA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.olegsych.com/2009/07/mvp-award/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.olegsych.com/2009/07/mvp-award/</feedburner:origLink></item>
		<item>
		<title>Getting and compiling T4 Toolbox source code</title>
		<link>http://feedproxy.google.com/~r/olegsych/~3/cRyEpqI9yM0/</link>
		<comments>http://www.olegsych.com/2009/06/getting-and-compiling-t4-toolbox-source-code/#comments</comments>
		<pubDate>Sun, 07 Jun 2009 16:57:30 +0000</pubDate>
		<dc:creator>Oleg Sych</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[T4]]></category>

		<guid isPermaLink="false">http://www.olegsych.com/2009/06/getting-and-compiling-t4-toolbox-source-code/</guid>
		<description><![CDATA[This post provides detailed instructions on how to get source code of T4 Toolbox and compile it on your computer.]]></description>
			<content:encoded><![CDATA[<p>Over the past year, several people have asked me to provide instructions on how to compile <a href="http://www.olegsych.com/2007/12/text-template-transformation-toolkit/"><a href="http://www.codeplex.com/t4toolbox">T4 Toolbox</a>.</a> The process is not difficult, but since I don’t do it every day, I have to dig through my email archive to find all the steps every time I need to provide the answer. This seems to be as good time as any to write everything down, so here it goes…</p>
<p>You will need latest versions of the following tools installed in order to compile <a href="http://www.olegsych.com/2007/12/text-template-transformation-toolkit/"><a href="http://t4toolbox.codeplex.com" target="_blank">T4 Toolbox</a>.</a> </p>
<ul>
<li><a href="http://www.microsoft.com/visualstudio/en-us/products/professional">Visual Studio 2008 Professional </a>or Team edition </li>
<li><a href="http://code.msdn.microsoft.com/sourceanalysis/">StyleCop</a></li>
<li><a href="http://wix.sourceforge.net/releases/wix3.feed">WiX 3.0</a></li>
<li><a href="http://msdn.microsoft.com/en-us/vjsharp/bb188598.aspx">Visual J# 2.0 Redistributable Package</a></li>
<li><a href="http://sdctasks.codeplex.com">SDC Tasks</a></li>
</ul>
<h4>Installing Tools</h4>
<p>You can install most of the tools with default options. </p>
<ul>
<li>When installing <em>StyleCop</em>, make sure that <em>MSBuild integration files</em> feature is installed.</li>
</ul>
<p><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="StyleCop installation options" border="0" alt="StyleCop installation options" src="http://www.olegsych.com/wp-content/uploads/2009/06/image.png" width="498" height="384" /></p>
<ul>
<li><em>SDC Tasks</em> don’t have an installer; binary files come in a ZIP archive. For <a href="http://www.olegsych.com/2007/12/text-template-transformation-toolkit/">T4</a> Toolbox, you will need to extract these files to <em>C:\Windows\Microsoft.NET\Framework\v3.5</em> directory.</li>
</ul>
<p><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Extracting SDC Tasks" border="0" alt="Extracting SDC Tasks" src="http://www.olegsych.com/wp-content/uploads/2009/06/image1.png" width="441" height="377" /> </p>
<ul>
<li>Open the extracted <em>Microsoft.Sdc.Common.tasks</em> XML file and comment out the <em>&lt;PropertyGroup/&gt;</em> element in the beginning of the file (enclose it with &lt;!&#8211; and &#8211;&gt;). This element generates warnings during compilation. </li>
<li>Unless you have <em>BizTalk </em>installed on your workstation, you will also need to comment out the entire section at the bottom of this file that declares BizTalk tasks implemented in <em>Microsoft.Sdc.Tasks.BizTalk.dll</em> assembly. Otherwise you will see a large number of errors referring to BizTalk assemblies during compilation.</li>
</ul>
</p>
<h4>Accessing Source Code</h4>
<p>You have two different ways of getting T4 Toolbox source code. If you have not been added to the list of developers, </p>
<ul>
<li>On the <a href="http://t4toolbox.codeplex.com/SourceControl/ListDownloadableCommits.aspx">Source Code tab of the project page,</a> click a <em>Download</em> link for the latest check-in.</li>
</ul>
<p><a href="http://www.olegsych.com/wp-content/uploads/2009/06/image2.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Source Code page of T4 Toolbox project on Code Plex" border="0" alt="Source Code page of T4 Toolbox project on Code Plex" src="http://www.olegsych.com/wp-content/uploads/2009/06/image-thumb.png" width="580" height="342" /></a></p>
<ul>
<li>After accepting the license agreement, you will be prompted to download a ZIP archive that contains the latest version of the T4 Toolbox source code. Save the file to your local hard drive first and unblock it before extracting the files. Unless you unblock the ZIP archive first, the Visual Studio will not “trust” it and you will get obscure security errors and warnings later on.</li>
</ul>
<p><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Unblock downloaded ZIP archive" border="0" alt="Unblock downloaded ZIP archive" src="http://www.olegsych.com/wp-content/uploads/2009/06/image3.png" width="368" height="503" /> </p>
<ul>
<li>Extract all files from this archive to a folder on your hard drive, such as <em>C:\T4Toolbox</em>, and open <em>T4Toolbox.sln</em> located in the <em>Source</em> subfolder.</li>
</ul>
<p><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="T4 Toolbox source code on local hard drive" border="0" alt="T4 Toolbox source code on local hard drive" src="http://www.olegsych.com/wp-content/uploads/2009/06/image4.png" width="488" height="316" /> </p>
<ul>
<li>When Visual Studio opens T4 Toolbox solution for the first time, select the <em>Load project normally </em>option. T4Toolbox.csproj uses MSBuild extensions from SDC tasks and StyleCop, you will need to select this option in order to compile it.</li>
</ul>
<p><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://www.olegsych.com/wp-content/uploads/2009/06/image5.png" width="552" height="390" /> </p>
<p>At this point, you should be able to compile the T4 toolbox. Make changes until it works the way you need it and then <a href="http://t4toolbox.codeplex.com/SourceControl/UploadPatch.aspx">upload the files you modified as a patch on CodePlex</a>. Myself or someone else will take a look at the changes you’ve made and commit them to the main source code of the project.</p>
</p>
</p>
</p>
<h4>Using Team Explorer</h4>
<p>When you are regularly working on T4 Toolbox source code, having to download a source code snapshot becomes a hassle. When your <a href="http://www.codeplex.com/">CodePlex</a> account has been added to the list of <a href="http://t4toolbox.codeplex.com/People/ProjectPeople.aspx">T4 Toolbox developers</a>, you can start using Team Explorer from Visual Studio.</p>
<ul>
<li>Download and install Team Explorer from <a href="http://www.microsoft.com/downloads/details.aspx?familyid=0ED12659-3D41-4420-BBB0-A46E51BFCA86&amp;displaylang=en">here</a>. </li>
<li>Once you have it installed, go to <a href="http://t4toolbox.codeplex.com/">T4 Toolbox page on CodePlex</a>, make sure you are logged (1), open the Source Code tab (2) and then click the Visual Studio Team Explorer link (3). On the right-hand side, you will see the information you will need to use in Team Explorer (4). </li>
</ul>
<p><a href="http://www.olegsych.com/wp-content/uploads/2009/06/image6.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Team Explorer instructions" border="0" alt="Team Explorer instructions" src="http://www.olegsych.com/wp-content/uploads/2009/06/image-thumb1.png" width="580" height="313" /></a> </p>
<ul>
<li>In <em>Visual Studio</em>, select <em>View-&gt;Team Explorer</em> from the main menu.</li>
<li>In <em>Team Explorer</em>, click <em>Add Existing Team Project</em> button</li>
<li>In the <em>Connect to Team Foundation Server </em>dialog, click <em>Servers</em> button</li>
<li>In the <em>Add/Remove Team Foundation Server </em>dialog, click <em>Add </em>button</li>
<li>In the <em>Add Team Foundation Server</em> dialog, enter server name, port number and protocol from the CodePlex page and click OK.</li>
</ul>
<p><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Add T4Toolbox Project to Team Explorer" border="0" alt="Add T4Toolbox Project to Team Explorer" src="http://www.olegsych.com/wp-content/uploads/2009/06/image7.png" width="580" height="480" /> </p>
<ul>
<li>Back in the <em>Add/Remove Team Foundation Server</em> dialog, click <em>Close </em>button</li>
<li>Back in the <em>Connect to Team Foundation Server </em>dialog, select <em>T4Toolbox </em>project and click <em>OK</em> button</li>
<li>Back in <em>Team Explorer</em>, you should now see the <em>T4Toolbox </em>project and its information. </li>
</ul>
<p><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://www.olegsych.com/wp-content/uploads/2009/06/image8.png" width="292" height="270" /> </p>
<ul>
<li>Double-click the <em>Source Control </em>node to open <em>Source Control Explorer</em></li>
</ul>
<p><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Source Control Explorer" border="0" alt="Source Control Explorer" src="http://www.olegsych.com/wp-content/uploads/2009/06/image9.png" width="580" height="294" /> </p>
</p>
</p>
<ul>
<li>In <em>Source Control Explorer</em>, select <em>T4Toolbox </em>folder on the left side and click the <em>Not mapped</em> link on the right. </li>
<li>In the <em>Map </em>dialog, enter name of the local folder you want to use for T4 Toolbox source code and click <em>Map </em>button.</li>
</ul>
<p><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Map workspace dialog" border="0" alt="Map workspace dialog" src="http://www.olegsych.com/wp-content/uploads/2009/06/image10.png" width="580" height="177" /></p>
<ul>
<li>Back in <em>Source Control Explorer</em>, click <em>Get Latest Version</em>&#160; button to download the source code to your local hard drive. </li>
<li>Once downloaded, double-click <em>T4Toolbox.sln </em>in the <em>Source </em>sub-folder to open the solution.</li>
</ul>
<p><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Get Latest Version and Open Solution from Source Control Explorer" border="0" alt="Get Latest Version and Open Solution from Source Control Explorer" src="http://www.olegsych.com/wp-content/uploads/2009/06/image11.png" width="580" height="294" /> </p>
</p>
<p>At this point, you can check files out, change them and check them in. The source control functionality is similar to Visual SourceSafe and Subversion, so it should be familiar to most developers.</p>
<p>&copy;2009 <a href="http://www.olegsych.com">Oleg Sych</a>. All Rights Reserved.</p>.<img src="http://feeds.feedburner.com/~r/olegsych/~4/cRyEpqI9yM0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.olegsych.com/2009/06/getting-and-compiling-t4-toolbox-source-code/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.olegsych.com/2009/06/getting-and-compiling-t4-toolbox-source-code/</feedburner:origLink></item>
		<item>
		<title>T4 Toolbox: LINQ to SQL schema generator</title>
		<link>http://feedproxy.google.com/~r/olegsych/~3/5Ppb6-NzUXM/</link>
		<comments>http://www.olegsych.com/2009/05/t4-toolbox-linq-to-sql-schema-generator/#comments</comments>
		<pubDate>Tue, 19 May 2009 23:40:53 +0000</pubDate>
		<dc:creator>Oleg Sych</dc:creator>
		
		<category><![CDATA[Articles]]></category>

		<category><![CDATA[C#]]></category>

		<category><![CDATA[Code Generation]]></category>

		<category><![CDATA[LINQ to SQL]]></category>

		<category><![CDATA[SQL]]></category>

		<category><![CDATA[T4]]></category>

		<category><![CDATA[Visual Studio]]></category>

		<guid isPermaLink="false">http://www.olegsych.com/2009/05/t4-toolbox-linq-to-sql-schema-generator/</guid>
		<description><![CDATA[This article describes how to use model-first approach to develop database applications using LINQ to SQL and version 9.5 of T4 Toolbox.]]></description>
			<content:encoded><![CDATA[<p>LINQ to SQL <a href="http://msdn.microsoft.com/en-us/library/system.data.linq.datacontext.aspx">DataContext</a> class provides <a href="http://msdn.microsoft.com/en-us/library/system.data.linq.datacontext.createdatabase.aspx">CreateDatabase</a> method, which can create an empty database based on the entity model. You can create a new entity model using the built-in <a href="http://msdn.microsoft.com/en-us/library/bb384429.aspx">O/R Designer</a>; generate the application code and create initial version of the database when the application is deployed for the first time. However, once the database is populated with live data, it can no longer be changed by simply re-creating the entire database. Instead, ALTER scripts have to be used to modify the schema and preserve the existing data. In other words, built-in tools allow you to use <em>model-first</em> or <em>model-driven</em> approach with LINQ to SQL only while developing initial version of the database application. The built-in tools don’t support an <em>ongoing</em> model-first development.</p>
<p>This limitation of the built-in LINQ to SQL functionality is one of the reasons developers start using a second tool, such as <a href="http://msdn.microsoft.com/en-us/library/ms171971.aspx">SQL Server Database Diagrams</a>, <a href="http://msdn.microsoft.com/en-us/library/ms182014.aspx">Visio for Enterprise Architects</a> or <a href="http://www.sparxsystems.com">Enterprise Architect by Sparx Systems</a>, and designing the database schema separately from the application model. While this approach works, it significantly increases complexity of the development process. Every change now needs to be made in two places - the database model and the application model. In all but trivial cases, making these changes by hand is too tedious and error-prone to be practical. You are better off choosing one model and somehow synchronizing it with the other. Today, developers typically choose database model as the source of truth and update the entity model based on it, or in other words, use <em>database-driven </em>or <em>database-first </em>approach.</p>
<p>LINQ to SQL includes two tools that allow you to generate .dbml from an existing database - O/R Designer and <a href="http://msdn.microsoft.com/en-us/library/bb386987.aspx">SqlMetal.exe</a> . Unfortunately, both of these tools overwrite existing dbml and don’t allow you to preserve customizations made in the raw relational model imported from the database. SqlMetal also allows you to generate application code from a database directly. By choosing these tools, you are limiting your LINQ to SQL model to a direct representation of your relational database schema and eliminate the possibility of taking advantage of the object-oriented features the framework supports, such as inheritance of entity classes, member access and virtual member modifiers. Alternatively, you can use these tools to create the initial version of the entity model you will customize later, however that brings you back to the issue of maintaining two models separately.</p>
<p>There are third-party tools that make ongoing <em>database-driven </em>development of LINQ to SQL applications more practical. In particular, <a href="http://www.plinqo.com/">PLINQO</a>, a set of code generation templates developed by <a href="http://www.codesmithtools.com">CodeSmith</a>, includes a sophisticated model synchronization logic, which updates .dbml based on database schema while attempting to preserve the customizations. However, these tools don’t eliminate the fundamental requirement of maintaining the two models separately. By itself, this requirement is not a problem. On a large-scale project with a complex database schema, this may well be a necessity. However, on a small- to medium-scale project, having to maintain the two models separately is often an additional, unnecessary burden. </p>
<p><a href="http://www.codeplex.com/t4toolbox/Release/ProjectReleases.aspx">Build 9.5 of T4 Toolbox</a> extends the <a href="http://www.olegsych.com/2009/01/t4-toolbox-linq-to-sql-classes-generator">LINQ to SQL generator</a> introduced in version 9.1 with support for database schema generation. This gives you the ability to generate both application code, such as entity and data context classes, and database code, such as table, primary and foreign key scripts, from a single LINQ to SQL dbml file in your solution. Generated database scripts can be automatically added to a <a href="http://msdn.microsoft.com/en-us/teamsystem/dd408380.aspx">VSTS Database</a> project, which will automatically handle majority of database deployment issues by automatically generating the ALTER scripts. In other words, <a href="http://www.olegsych.com/2007/12/text-template-transformation-toolkit/"></a>combined with VSTS Database edition, <a href="http://www.codeplex.com/t4toolbox">T4 Toolbox</a></a>&#160; allows you to use <em>model-driven</em> or <em>model-first</em> approach for <em>ongoing </em>development of LINQ to SQL applications.</p>
<h4>Usage</h4>
<ul>
<li>Download and install the latest version of T4 Toolbox from <a href="http://www.codeplex.com/t4toolbox/Release/ProjectReleases.aspx">CodePlex</a>. </li>
<li>In Visual Studio, create a new or open an existing C# project and select <em>Project-&gt;Add New Item</em> in the main menu. </li>
<li>In the Add New Item dialog, select <em>Code Generation-&gt;LINQ to SQL model</em> </li>
</ul>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Add new LINQ to SQL model" border="0" alt="Add new LINQ to SQL model" src="http://www.olegsych.com/wp-content/uploads/2009/05/image6.png" width="580" height="318" /> </p>
<ul>
<li>Enter the name you want to use for the new LINQ to SQL model (.dbml) file. Note that this name also determines name of the <em>DataContext </em>class that will be generated (<em>OrderEntryDataContext</em> will be generated for <em>OrderEntry.dbml</em>). Click the <em>Add </em>button when finished. </li>
</ul>
<p>Just like with the <a href="http://www.olegsych.com/2009/01/t4-toolbox-linq-to-sql-classes-generator">previous version</a> of this template, you will see that two files, a .dbml and a .tt, were added to your project. This time, instead of populating the entity model by dragging and dropping tables from the Server Explorer to the O/R Designer, take a couple of minutes to create the model from scratch and take advantage of some of the LINQ to SQL features like inheritance and associations. There is no need to enter mapping information, such as table or column names and database types. The generator will automatically deduce them from the type names, property names and CLR types respectively. </p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="LINQ to SQL O/R designer" border="0" alt="LINQ to SQL O/R designer" src="http://www.olegsych.com/wp-content/uploads/2009/05/image7.png" width="580" height="317" /></p>
<p>Alternatively, you can download the sample source code accompanying this article. The sample includes an entity model of a simplistic Order Entry application shown above. This model showcases some of the features supported by the code generator, including auto-generated properties (<em>Contact.Id</em>), version properties (<em>Contact.RowVersion</em>), derived types (<em>Employee, Customer, Vendor</em>) , associations (<em>Contact_Employee</em>) and associations where a derived type serves as a parent (<em>Customer_Order</em>). </p>
<ul>
<li>Add a new VSTS database project to the solution. </li>
</ul>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Add new database project" border="0" alt="Add new database project" src="http://www.olegsych.com/wp-content/uploads/2009/05/image8.png" width="580" height="345" /></p>
<p>Make sure to select an appropriate project type in the <em>Database Projects</em>&#160; folder of the <em>Add New Project</em> dialog. Legacy database project template, located under <em>Other Project Types </em>-&gt; <em>Database</em> will not work. If you don’t have Database edition of VSTS installed, you can use any C# project type instead.</p>
<ul>
<li>In the previously created .tt file (<em>OrderEntry.tt</em> in this example), modify the code to assign <em>DatabaseProject </em>property of the <em>LinqToSqlGenerator</em> instance. </li>
</ul>
<pre class="code"><span style="color: black">&lt;#@ </span><span style="color: brown">template </span><span style="color: red">language</span><span style="color: black">=&quot;</span><span style="color: blue">C#v3.5</span><span style="color: black">&quot; </span><span style="color: red">hostspecific</span><span style="color: black">=&quot;</span><span style="color: blue">True</span><span style="color: black">&quot; </span><span style="color: red">debug</span><span style="color: black">=&quot;</span><span style="color: blue">True</span><span style="color: black">&quot; #&gt;
&lt;#@ </span><span style="color: brown">output </span><span style="color: red">extension</span><span style="color: black">=&quot;</span><span style="color: blue">log</span><span style="color: black">&quot; #&gt;
&lt;#@ </span><span style="color: brown">include </span><span style="color: red">file</span><span style="color: black">=&quot;</span><span style="color: blue">T4Toolbox.tt</span><span style="color: black">&quot; #&gt;
&lt;#@ </span><span style="color: brown">include </span><span style="color: red">file</span><span style="color: black">=&quot;</span><span style="color: blue">T4Toolbox\LinqToSql.tt</span><span style="color: black">&quot; #&gt;
&lt;#
    </span><span style="color: green">// Generate entity classes from a LINQ to SQL class model (.dbml file)
    </span><span style="color: black">LinqToSqlGenerator generator = </span><span style="color: blue">new </span><span style="color: black">LinqToSqlGenerator();
    generator.DbmlFile = </span><span style="color: maroon">&quot;OrderEntry.dbml&quot;</span><span style="color: black">;
    generator.DatabaseProject = </span><span style="color: maroon">@&quot;..\Database\Database.dbproj&quot;</span><span style="color: black">;
</span><span style="color: black">    generator.Run();
#&gt;</span></pre>
<p><img style="border-right-width: 0px; margin: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Generated Database Code" border="0" alt="Generated Database Code" align="right" src="http://www.olegsych.com/wp-content/uploads/2009/05/image9.png" width="238" height="260" /> <em>DatabaseProject</em> value is a path to the database project file, relative to the location of the .tt file. When you save the .tt file, it will generate table, primary and foreign key scripts in this project. At this point, you can build the <a href="http://msdn.microsoft.com/en-us/teamsystem/dd408380.aspx">VSTS Database</a> project and deploy the <em>OrderEntry</em> database to a SQL server. Detailed discussion of the VSTS Database project functionality is outside of scope this article, suffice it to say that this should require only right-clicking the database project in Solution Explorer and selecting <em>Deploy</em> from the context menu.</p>
<p>As you continue using O/R designer to add new properties and types to the LINQ to SQL model, simply right-click the <em>OrderEntry.tt </em>file in the Solution Explorer and select <em>Run Custom Tool</em> to regenerate the database code, build the database project, deploy and let VSTS automatically apply ALTER scripts to the existing database.</p>
<h4>Feature Highlights</h4>
<p>Let’s review some the features supported by this code generator. </p>
<pre class="code"><span style="color: blue">CREATE TABLE </span>dbo.Contact
(
    Id <span style="color: blue">INT NOT NULL IDENTITY</span>,
    Type <span style="color: blue">tinyint</span>,
    <span style="color: blue">RowVersion ROWVERSION</span>,
    FirstName <span style="color: blue">NVARCHAR</span>(4000),
    LastName <span style="color: blue">NVARCHAR</span>(4000),
    StreetAddress <span style="color: blue">NVARCHAR</span>(4000),
    City <span style="color: blue">NVARCHAR</span>(4000),
    State <span style="color: blue">NVARCHAR</span>(4000),
    Zip <span style="color: blue">NVARCHAR</span>(4000),
    Phone <span style="color: blue">NVARCHAR</span>(4000),
    Email <span style="color: blue">NVARCHAR</span>(4000),
    SocialSecurityNumber <span style="color: blue">NVARCHAR</span>(4000),
    EmergencyContactId <span style="color: blue">INT</span>,
    AccountNumber <span style="color: blue">NVARCHAR</span>(4000),
    CreditCardNumber <span style="color: blue">NVARCHAR</span>(4000),
    CreditCardExpiration <span style="color: blue">NVARCHAR</span>(4000)
);</pre>
<h5>Derived types mapped to base table</h5>
<p>The generator automatically generates columns for derived types, such as <em>Employee</em>, in the table of their base type, such as <em>Contact</em>. In particular, <em>SocialSecurityNumber</em> is a property of the Employee type, stored in the <em>Contact </em>table.</p>
<h5>IDENTITY columns</h5>
<p>The generator automatically maps integer properties with <em>Auto Generated Value</em> attribute set to true, such as <em>Id</em>,&#160; to <a href="http://msdn.microsoft.com/en-us/library/ms174979.aspx">IDENTITY</a> columns.</p>
<h5>ROWVERSION data type</h5>
<p>The generator automatically maps byte[] and <a href="http://msdn.microsoft.com/en-us/library/system.data.linq.binary.aspx">Binary</a> properties with <em>Time Stamp</em> attribute set to true, such as <em>RowVersion</em>, to the <a href="http://msdn.microsoft.com/en-us/library/ms182776.aspx">ROWVERSION</a> data type.</p>
<h5>Enum columns</h5>
<p>The generator automatically maps enum properties, such as <em>Type</em> property of the <em>Contact </em>class, to SQL data type INT. You can also specify the server data type explicitly. In the application, the property will be generated with the original enum type.</p>
<pre class="code"><span style="color: blue">private </span><span style="color: #2b91af">ContactType </span>type;

[<span style="color: #2b91af">Column</span>(Name = <span style="color: #a31515">&quot;Type&quot;</span>, <span style="color: green">/* &#8230; */ </span>DbType = <span style="color: #a31515">&quot;tinyint&quot;</span>)]
<span style="color: blue">public </span><span style="color: #2b91af">ContactType </span>Type { <span style="color: green">/* &#8230; */ </span>}</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>This allows you to write strongly-typed queries like so:</p>
<pre class="code"><span style="color: blue">var </span>dc = <span style="color: blue">new </span><span style="color: #2b91af">OrderEntryDataContext</span>(<span style="color: #2b91af">Settings</span>.Default.Database);
<span style="color: blue">var </span>employees = <span style="color: blue">from </span>c <span style="color: blue">in </span>dc.Contacts
                <span style="color: blue">where </span>c.Type == <span style="color: #2b91af">ContactType</span>.Employee
                <span style="color: blue">select </span>c;</pre>
<p><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a></p>
<h5>Primary keys</h5>
<pre class="code"><span style="color: blue">ALTER TABLE </span>dbo.Contact
    <span style="color: blue">ADD CONSTRAINT </span>PK_Contact
    <span style="color: blue">PRIMARY KEY CLUSTERED </span>(Id);</pre>
<p>The generator automatically produces a primary key script for properties with <em>Primary Key</em> attribute set to true.</p>
<h5>Delimited Identifiers</h5>
<pre class="code"><span style="color: blue">CREATE TABLE </span>dbo.[Order]
(
    Id <span style="color: blue">INT NOT NULL IDENTITY</span>,
    OrderDate <span style="color: blue">DATETIME NOT NULL</span>,
    EmployeeId <span style="color: blue">INT NOT NULL</span>,
    ProductId <span style="color: blue">INT NOT NULL</span>,
    <span style="color: blue">RowVersion ROWVERSION</span>,
    CustomerId <span style="color: blue">INT NOT NULL</span>,
    Price <span style="color: blue">DECIMAL</span>(29,4) <span style="color: blue">NOT NULL</span>,
    PONumber <span style="color: blue">NVARCHAR</span>(4000)
);</pre>
<p>The generator automatically uses delimited identifiers to avoid errors when original identifier is a reserved SQL keyword, such as <em>Order</em>, or contains spaces, such as <em>Order&#160; Details</em>. Otherwise, the generator uses the original, un-delimited identifiers to improve readability.</p>
<h5>Foreign Keys</h5>
<pre class="code"><span style="color: blue">ALTER TABLE </span>dbo.[Order]
    <span style="color: blue">ADD CONSTRAINT </span>FK_Customer_Order
    <span style="color: blue">FOREIGN KEY </span>(CustomerId)
    <span style="color: blue">REFERENCES </span>dbo.Contact (Id);</pre>
<p>The generator automatically produces foreign key scripts for associations. Note that in case of <em>Customer_Order</em> association, the parent type <em>Customer</em> is actually derived from <em>Contact</em>. The foreign key correctly references the base table, however the generated association property (shown below), is of the derived type, <em>Customer</em>.</p>
<pre class="code">[<span style="color: #2b91af">Association</span>(Name = <span style="color: #a31515">&quot;Customer_Order&quot;</span>, <span style="color: green">/* &#8230; */ </span>IsForeignKey = <span style="color: blue">true</span>)]
<span style="color: blue">public </span><span style="color: #2b91af">Customer </span>Customer { <span style="color: green">/* &#8230; */ </span>}</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<h4>Sample Source Code</h4>
<p>Sample source code, available for download below, includes a solution with three projects - Model, Database and Application. <em>Model</em> is a C# class library project that contains <em>OrderEntry.dbml</em> (LINQ to SQL model) and <em>OrderEntry.tt</em> (code generator). Entity and Data Context classes are generated in the Model project, while SQL scripts are generated in the <em>Database</em> project. Note that this project requires VSTS Database edition. <em>Application</em> is a C# console application that creates a sample database on the local SQL Server instance, populates it with sample data and executes several queries.</p>
<h4>Closing Thoughts</h4>
<p>The new version of LINQ to SQL generator in T4 Toolbox allows you to use model-first approach for ongoing developing database applications. </p>
<p>So what’s the big deal? <em>Simplicity</em>. </p>
<ul>
<li>There is no need to use a separate modeling tool when developing a database application. You can generate both database and application code without leaving Visual Studio IDE. </li>
<li>There is only one diagram to maintain, which reflects both entity and database models. If you are editing both at the same time, there is no way you can forget update one of them after updating the other.</li>
<li>There is only one step in the code generation process - <em>Run Custom Tool</em> from <em>Solution Explorer</em>. You don’t need to remember to make the changes in the modeling tool, export the schema, build the schema, synchronize the .dbml file with the schema and finally generate the application code from .dbml. </li>
</ul>
<p>What’s the catch then? <em>Limited scalability and flexibility</em>.</p>
<ul>
<li>O/R designer is limited to a single diagram, which puts practical limitations on the number of tables you can manage with this approach. </li>
<li>What you can generate is limited by what you can model in the O/R designer - tables, primary keys and foreign keys. (INSERT, UPDATE and DELETE procedures can also be generated, this is under development now). </li>
<li>Entity and database models are closely related and cannot be developed separately. If you have an existing database, you may not be able to use this approach.</li>
</ul>
<p>Will it work for you? <em>It depends</em>. </p>
<p>This approach will work best on <a href="http://en.wikipedia.org/wiki/Greenfield_project">greenfield projects</a> with a small- to medium-size database and teams who prefer implementing business logic in application code, not stored procedures and triggers. You can certainly optimize time-critical logic by selectively implementing it stored procedures and exposing them in the LINQ to SQL model. However, you will be swimming against the current if you want to rely on the stored procedures extensively. On brownfield projects, this approach will work as well if you have a database of appropriate size and can limit database modifications to the O/R Designer. This approach will not work well if you have a database with hundreds of tables and/or multiple database developers actively creating tables and stored procedures.</p>
<h5>Download</h5>
<ul>
<li><a href="http://www.codeplex.com/t4toolbox/Release/ProjectReleases.aspx">T4 Toolbox</a> </li>
<li><a href="http://www.olegsych.com/wp-content/uploads/2009/05/t4-toolbox-linq-to-sql-schema-generator.zip">Sample source code</a> </li>
</ul>
<p>&copy;2009 <a href="http://www.olegsych.com">Oleg Sych</a>. All Rights Reserved.</p>.<img src="http://feeds.feedburner.com/~r/olegsych/~4/5Ppb6-NzUXM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.olegsych.com/2009/05/t4-toolbox-linq-to-sql-schema-generator/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.olegsych.com/2009/05/t4-toolbox-linq-to-sql-schema-generator/</feedburner:origLink></item>
		<item>
		<title>Crossing Domain Boundaries: Windows Authentication</title>
		<link>http://feedproxy.google.com/~r/olegsych/~3/-0aRuNhgyLs/</link>
		<comments>http://www.olegsych.com/2009/05/crossing-domain-boundaries-windows-authentication/#comments</comments>
		<pubDate>Sat, 02 May 2009 19:19:00 +0000</pubDate>
		<dc:creator>Oleg Sych</dc:creator>
		
		<category><![CDATA[Articles]]></category>

		<category><![CDATA[Security]]></category>

		<category><![CDATA[SQL]]></category>

		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://www.olegsych.com/2009/05/crossing-domain-boundaries-windows-authentication/</guid>
		<description><![CDATA[This article describes a set of simple configuration changes and utilities to make most applications using integrated Windows authentication work correctly accross domain boundaries.]]></description>
			<content:encoded><![CDATA[<p>Today, majority of applications on the Microsoft platform rely on or provide support for integrated Windows authentication. Using integrated Windows authentication allows applications to completely avoid persisting custom login credentials and thus eliminates the possibility of an attacker finding them in a configuration file, registry or database and gaining unauthorized access to the system. Microsoft has been promoting use of integrated Windows authentication for years and most software vendors (or perhaps just those who truly care about having customers on the Microsoft platform) support it as an option in their products.</p>
<p>As a consultant, I feel obligated to advise my clients on using integrated Windows authentication as the most secure authentication mechanism for their networks and custom solutions. Unfortunately, as a consultant, I also need to access my clients’ networks from my Catapult laptop, across domain boundaries. This is where integrated Windows authentication makes my job more difficult. Typically, I cannot use my <a href="http://www.catapultsystems.com/">Catapult</a> domain credentials to access resources on the client’s domain and have to supply an alternative set of Windows credentials explicitly. Some applications, like Internet Explorer and Visual Studio are smart enough to prompt you to enter Windows credentials when necessary. While these applications may prompt you to enter credentials more often than you might like, other applications don’t prompt you at all and simply fail. In particular, database applications connecting to SQL Server will not prompt for credentials and display the infamous “<a href="http://search.live.com/results.aspx?q=Cannot+generate+SSPI+context">Cannot establish SSPI context</a>” error when you try use them across domain boundaries.</p>
<p>Thankfully, there is a relatively small number of tricks you need to use to get most applications using integrated Windows authentication work successfully across domain boundaries. These tricks are described below, but before you rush to try them, make sure you have configured <a href="http://www.olegsych.com/2009/04/crossing-domain-boundaries-name-resolution/">name resolution</a> and can successfully connect to a network resource on the target domain using it’s name. Windows authentication will not work without successful name resolution.</p>
<h4>Stored user names and passwords</h4>
<p>Windows allows you to store login credentials for various authentication mechanisms, including Windows or <a href="http://en.wikipedia.org/wiki/Active_Directory">Active Directory</a> credentials. You can store a single Windows login (<em>CLIENT\account</em>) and password for an entire domain (<em>*.client.lan</em>) and Windows will use these credentials automatically whenever you access any computer on it.</p>
<p>Not all types of applications support stored user names and passwords. HTTP applications, such as Internet Explorer, Team Foundation Explorer in Visual Studio, and other applications using WebClient, are one of them. Whenever you type <a href="http://target.client.lan">http://target.client.lan</a> in Internet Explorer, the WebClient will send the matching stored credentials to the target computer automatically, without prompting you. Windows Explorer, Performance Monitor, Event Viewer and other applications relying on network shares also support this mechanism. As long as you have credentials stored, these applications will just work, as if your computer was a member of the target domain. Here is how you set it up.</p>
<ul>
<li>Open <em>User Accounts</em> from <em>Control Panel</em> and click the <em>Manage your network passwords</em> link on the left.</li>
</ul>
<p><img border="0" src="http://www.olegsych.com/wp-content/uploads/2009/05/image18.png" alt="image18" style="display: block; float: none; margin-left: auto; margin-right: auto; border-width: 0px" title="image18" height="279" width="561" /></p>
<ul>
<li>If you are using an older version of Windows, such as XP or 2003 Server, you will need to click the <em>Manage Passwords</em> button on the <em>Advanced</em> tab of the <em>User Accounts</em> dialog.</li>
</ul>
<p><img border="0" src="http://www.olegsych.com/wp-content/uploads/2009/05/managepasswordsoldwindows.png" alt="ManagePasswordsOldWindows" style="display: block; float: none; margin-left: auto; margin-right: auto; border-width: 0px" title="ManagePasswordsOldWindows" height="455" width="404" /></p>
<ul>
<li>In the <em>Stored User Names and Passwords</em> dialog you need to click the <em>Add </em>button and create a credential entry for the target domain you need to access. Assuming that one of the computers you need to access has a fully-qualified domain name <em>target.client.lan</em>, you want to store credentials for a wildcard <em><strong>*.client.lan</strong></em>, which will used when you access any computers on that domain.</li>
</ul>
<h6><img border="0" src="http://www.olegsych.com/wp-content/uploads/2009/05/image29.png" alt="image29" style="display: block; float: none; margin-left: auto; margin-right: auto; border-width: 0px" title="image29" height="546" width="461" /> </h6>
<p>You can find more information about storing user names and passwords in the Microsoft knowledge base article <a href="http://support.microsoft.com/kb/281660">281660</a>.</p>
<h4>Internet security zone</h4>
<p>As an added security measure, Internet Explorer will send your current or stored credentials to the target host only when it believes to be a member of the <em>Intranet </em>zone. It will assume that any host addressed with a fully-qualified domain name such as <em>target.client.lan </em>is on the public internet and will not send the credentials automatically. This protects your identity from being stolen by a rouge web site getting your Windows credentials without your permission.</p>
<p>As you can see from the snapshot of Internet Explorer security settings below, even adding the target host to the list of trusted web sites will not work.</p>
<p><img border="0" src="http://www.olegsych.com/wp-content/uploads/2009/05/image.png" alt="image" style="display: block; float: none; margin-left: auto; margin-right: auto; border-width: 0px" title="image" height="483" width="427" /></p>
<p>In order for Windows authentication to work automatically across domain boundaries, without you having to type in your credentials for every page, you will need to add a particular host or its entire domain to the <em>Local Intranet </em>zone.</p>
<ul>
<li>Select <em>Internet Options </em>in <em>Control Panel</em></li>
<li>On the <em>Security </em>tab of the <em>Internet Properties </em>dialog, select <em>Local intranet</em> icon and click <em>Sites </em>button</li>
<li>In the <em>Local intranet </em>dialog, click <em>Advanced </em>button</li>
</ul>
<p><img border="0" src="http://www.olegsych.com/wp-content/uploads/2009/05/image26.png" alt="image26" style="display: block; float: none; margin-left: auto; margin-right: auto; border-width: 0px" title="image26" height="519" width="580" /></p>
<ul>
<li>In the second <em>Local intranet</em> dialog, enter URL of the web site and click <em>Add </em>button.</li>
</ul>
<p>Just like with stored user names and passwords, you can use wildcards that apply to all computers on the target domain. For example, if you enter <em>http://*.client.lan</em>, Internet Explorer will consider <em>target.client.lan </em>and all other computers on the <em>client.lan </em>domain to be in the <em>Local intranet </em>zone and send stored user names and passwords to them automatically.</p>
<h4>WebClient configuration</h4>
<p>Unfortunately, Microsoft Office applications will continue prompting you to enter credentials when accessing files stored on a SharePoint site even after you add the target domain to the Local intranet zone. You will need to modify WebClient configuration in registry to prevent this from happening.</p>
<ul>
<li>Open <em>HKLM\System\CurrentControlSet\Services\WebClient\Parameters</em> key in <em>Registry Editor</em>.</li>
</ul>
<p><img border="0" src="http://www.olegsych.com/wp-content/uploads/2009/05/image1.png" alt="image" style="display: inline; border-width: 0px" title="image" height="228" width="581" /></p>
<ul>
<li>Double-click the <em>AuthForwardServerList</em> value</li>
<li>In the <em>Edit Multi-String </em>dialog, enter the target URL on a separate line and click OK.</li>
</ul>
<p><img border="0" src="http://www.olegsych.com/wp-content/uploads/2009/05/image2.png" alt="image" style="display: block; float: none; margin-left: auto; margin-right: auto; border-width: 0px" title="image" height="325" width="364" /></p>
<p>This setting also supports wildcards. If you enter <em>http://*.client.lan</em>, Microsoft Office applications will automatically send stored Windows credentials to any SharePoint you access on the <em>client.lan </em>domain. You can learn more about this in Microsoft knowledge base article <a href="http://support.microsoft.com/kb/941050">941050</a>.</p>
<h4>Runas /netonly</h4>
<p>Some applications don’t support stored user names and passwords. For example SQL Server Management Studio will not be able to connect to a database on a different domain using Windows authentication. In these cases you can use the <a href="http://technet.microsoft.com/en-us/library/bb490994.aspx">runas</a> command with <em>netonly</em> option and make the application access network resources under a different set of credentials.</p>
<pre class="code">c:\&gt;runas /user:CLIENT\account /netonly ssms.exe
Enter the password for CLIENT\account:
Attempting to start ssms.exe as user "CLIENT\account" ...</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>When started with the command line above, SQL Server Management Studio will use <em>CLIENT\account</em> to connect to all SQL servers instead of the actual account you used to log into your computer (<em>CATAPULT\osych</em> in my case). In other words, if you need to connect to a database on <em>sqlserver.client.lan</em>, it will use <em>CLIENT\account</em> credentials you supply.</p>
<p>This trick works for all applications that need to connect to SQL Server using integrated windows authentication, not just SQL Server Management Studio. You can use it to run Visual Studio (<em>devenv.exe</em>) and your custom applications.</p>
<p>You can also use the <a href="http://technet.microsoft.com/en-us/sysinternals/cc300361.aspx">ShellRunas</a> utility to provide netonly credentials interactively. Once you downloaded and saved the utility in a permanent location on your hard drive, you will need to register it like so.</p>
<pre class="code">c:\Program Files (x86)\SysInternals&gt;ShellRunas /reg /quiet  

c:\Program Files (x86)\SysInternals&gt;ShellRunas /regnetonly /quiet</pre>
<p>The registration adds <em>Run as different user </em>and <em>Run as different user (netonly)</em> menu items to the shell (i.e. Explorer) context menus for executables.</p>
<p><img border="0" src="http://www.olegsych.com/wp-content/uploads/2009/05/image3.png" alt="image" style="display: block; float: none; margin-left: auto; margin-right: auto; border-width: 0px" title="image" height="561" width="441" /></p>
<p>You can start Visual Studio with netonly context by right-clicking it in the Start menu and selecting the option. Simply provide the credentials required by the target computer you want to access on the other domain and click OK.</p>
<p><img border="0" src="http://www.olegsych.com/wp-content/uploads/2009/05/image4.png" alt="image" style="display: block; float: none; margin-left: auto; margin-right: auto; border-width: 0px" title="image" height="353" width="439" /></p>
<p>While you can also run an application completely under another account, not just netonly, this will only work if the domain you are trying to access has a trust relationship with your own domain. Even then, running an application completely under another account is less convenient than netonly because it runs in a different user profile, loosing your settings, shortcuts and favorites. Remember to select netonly option as it is easy to accidentally omit it.</p>
<h4>Local accounts</h4>
<p>If none of the options described above works, your last resort is local accounts and workgroup authentication. In workgroup mode, when there is no Active Directory domain controller, i.e. no centralized authentication authority, Windows relies on having matching local accounts on all computers in a workgroup. For example, an application running under local Administrator on your computer, let’s say it’s called CATLAPTOP, can access computer called TARGET on another domain under <em>its </em>local Administrator account as long as CATLAPTOP\Administrator and TARGET\Administrator accounts have the same passwords on both computers. This works for any account, not just Administrator, subject to permissions assigned to the local account on the target computer.</p>
<p>Using local accounts and workgroup authentication appears to be the recommended approach for some advanced cross-domain networking scenarios, such as <a href="http://msdn.microsoft.com/en-us/library/9y5b4b4f.aspx">remote debugging</a> and SQL Server integrated security. However, these particular scenarios work with runas/netonly approach as well. Unlike the workgroup authentication approach, runas/netonly doesn’t require you to get access to a local account on each target computer. Maintaining these accounts is a hassle for IS administrators and they are typically reluctant to do it. You will probably want to use this option only as a last resort.</p>
<p>If you have to use this option, make sure that your local security policy allows workgroup authentication.</p>
<ul>
<li>Select <em>Local Security Policy</em> from <em>Control Panel</em> under <em>Administrative Tools</em></li>
<li>In the <em>Local Security Policy </em>console, find <em>Security Options </em>under <em>Local Policies</em></li>
</ul>
<p><img border="0" src="http://www.olegsych.com/wp-content/uploads/2009/05/image5.png" alt="image" style="display: inline; border-width: 0px" title="image" height="241" width="580" /></p>
<ul>
<li>Make sure that the <em>Network access: Sharing and security model for local accounts</em> option is set to <em>Classic - local users authenticate as themselves</em>.</li>
</ul>
<h4>Conclusion</h4>
<p>Relying on integrated Windows authentication and Active Directory for centralized authentication is a great way to make information systems in your organization more secure. While making life of users and administrators easier by allowing them to use and manage a single set of login credentials for various network resources and applications, integrated Windows authentication presents an additional barrier when you need to access network resources across domain boundaries. Luckily a relatively small set of configuration changes can help you solve most of these difficulties.</p>
<p>This article describes configuration changes and utilities in the order from easiest and most commonly used to most difficult and infrequently used. You will probably want to store credentials for the new domain and add it to the <em>Local intranet</em> security zone first. This enables most modern applications to access network resources on the target domain without errors and without bothering you with constant prompts for credentials. If you need to access Microsoft Office documents on a SharePoint site, you may also want to configure WebClient to automatically use your stored credentials instead of prompting you every time. For advanced scenarios, such as database applications and remote debugging, use the <em>runas </em>command with <em>netonly </em>option or its interactive equivalent, <em>ShellRunas</em>. If all other options fail, you may have to resort to using local accounts and workgroup authentication.</p>
<p>Name resolution and authentication are not the only problems you have to solve to access network resources. Advanced scenarios may require you to make changes in firewall, group policy, security policy, registry and file configurations a particular application may be affected by. Discussion of these scenarios is outside of scope of this article. You can usually find specific instructions in <a href="http://support.microsoft.com/">Microsoft knowledge base</a>.</p>
<p>&copy;2009 <a href="http://www.olegsych.com">Oleg Sych</a>. All Rights Reserved.</p>.<img src="http://feeds.feedburner.com/~r/olegsych/~4/-0aRuNhgyLs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.olegsych.com/2009/05/crossing-domain-boundaries-windows-authentication/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.olegsych.com/2009/05/crossing-domain-boundaries-windows-authentication/</feedburner:origLink></item>
		<item>
		<title>Crossing Domain Boundaries: Name Resolution</title>
		<link>http://feedproxy.google.com/~r/olegsych/~3/scSMrOG2kLA/</link>
		<comments>http://www.olegsych.com/2009/04/crossing-domain-boundaries-name-resolution/#comments</comments>
		<pubDate>Mon, 27 Apr 2009 02:32:11 +0000</pubDate>
		<dc:creator>Oleg Sych</dc:creator>
		
		<category><![CDATA[Articles]]></category>

		<category><![CDATA[DNS]]></category>

		<category><![CDATA[NetBIOS]]></category>

		<category><![CDATA[TCP/IP]]></category>

		<category><![CDATA[WINS]]></category>

		<guid isPermaLink="false">http://www.olegsych.com/2009/04/crossing-domain-boundaries-name-resolution/</guid>
		<description><![CDATA[This article provides an overview of DNS and NetBIOS and provides practical guidance on how to configure name resolution when accessing network resources and applications from another Active Directory domain.]]></description>
			<content:encoded><![CDATA[<p>You may be in a situation where you have to access network resources from another Active Directory domain. Perhaps you do business with another company and have to access files or applications from their network. This situation is very common when you are a consultant installing, configuring or building custom information systems for different clients. There are several challenges you have to solve or work around to access network resources across domain boundaries.</p>
<p>Assuming that you already connected to the client’s network with the help of DHCP, your first challenge is to get name resolution working. <em>Name resolution</em> is a process that converts human readable host names into numeric addresses used by TCP/IP. Whenever computer program uses a network address, such as a web URL <a href="http://target">http://target</a>, the host name has to be converted or resolved to an IP address before the target host can be accessed over the network from your computer. When both your computer and the target host are on the same domain, this process works seamlessly. However, when computer and the target host are on different domains, you may need to make additional configuration changes.</p>
<p>There are two name resolution mechanisms in active use today: <a href="http://technet.microsoft.com/en-us/library/bb727013.aspx">NetBIOS</a> and <a href="http://technet.microsoft.com/en-us/library/bb727007.aspx">DNS</a>. Although both of these these protocols were developed in the early 1980s, NetBIOS was implemented on the Windows platform first and then has fallen out of favor with release of Windows 2000 and Active Directory, which provided support for DNS. </p>
<pre class="code">C:\&gt;ipconfig /all

Windows IP Configuration

   Host Name . . . . . . . . . . . . : CATTAMLAPTOP
   Primary Dns Suffix  . . . . . . . : catapultsystems.com
   Node Type . . . . . . . . . . . . : Hybrid
   IP Routing Enabled. . . . . . . . : No
   WINS Proxy Enabled. . . . . . . . : No
   DNS Suffix Search List. . . . . . : catapultsystems.com
                                       dmz.catapultsystems.com

Ethernet adapter Local Area Connection:

   Connection-specific DNS Suffix  . : client.lan
   Description . . . . . . . . . . . : Broadcom NetXtreme 57xx Controller
   Physical Address. . . . . . . . . : 00-11-22-33-44-55
   DHCP Enabled. . . . . . . . . . . : Yes
   Autoconfiguration Enabled . . . . : Yes
   Link-local IPv6 Address . . . . . : fe80::3424:f17e:93ec:8912%11(Preferred)
   IPv4 Address. . . . . . . . . . . : 172.16.242.13(Preferred)
   Subnet Mask . . . . . . . . . . . : 255.255.0.0
   Lease Obtained. . . . . . . . . . : Thursday, April 23, 2009 4:12:45 PM
   Lease Expires . . . . . . . . . . : Thursday, April 30, 2009 4:12:45 PM
   Default Gateway . . . . . . . . . : 172.16.1.2
   DHCP Server . . . . . . . . . . . : 10.10.4.22
   DNS Servers . . . . . . . . . . . : 10.10.4.6
                                       10.10.4.8
   NetBIOS over Tcpip. . . . . . . . : Enabled</pre>
<p>You can tell which mechanism is available by looking at the output produced by <a href="http://technet.microsoft.com/en-us/library/cc755772.aspx">ipconfig</a> command. In particular, the <em>DNS Servers</em> setting will tell you if a DNS server is available for name resolution and <em>NetBIOS over Tcpip</em> setting will tell you if NetBIOS is enabled.</p>
<h4>Name resolution through DNS</h4>
<p><a href="http://en.wikipedia.org/wiki/Domain_Name_System">DNS</a> works in client-server mode, where your computer sends a name resolution request to a DNS server and the server sends back the IP address registered for the specified host name. To use DNS for name resolution, first you need to use the ipconfig command (shown above) to verify that a DNS server is available. Typically, this will be configured automatically, by DHCP, when your computer connects to the network. </p>
<p>Because the Domain Name System is hierarchical, DNS server cannot uniquely resolve a local name such as <em>target</em>. Before sending a host name to the server, DNS client will try to guess its fully-qualified domain name (<a href="http://en.wikipedia.org/wiki/FQDN">FQDN</a>), such as <em>target.client.lan</em>, based on the list of known DNS suffixes it has access to through various configuration settings. It will keep asking the configured DNS servers to resolve the potential names until it finds a match. The order of DNS servers and domain suffixes is important because the DNS client will use the first one it can resolve. If it happens to be a wrong guess, you will not be able to connect to the desired target host.</p>
<h5>Primary DNS suffix</h5>
<p>The primary DNS suffix a suffix of the fully-qualified domain name of your computer. As you can see in the <em>Windows IP Configuration</em> section of the <em>ipconfig </em>output below, the primary DNS suffix on my laptop is catapultsystems.com.</p>
<pre class="code">C:\&gt;ipconfig /all

Windows IP Configuration

   Host Name . . . . . . . . . . . . : CATTAMLAPTOP
   Primary Dns Suffix  . . . . . . . : catapultsystems.com
   Node Type . . . . . . . . . . . . : Hybrid
   IP Routing Enabled. . . . . . . . : No
   WINS Proxy Enabled. . . . . . . . : No
   DNS Suffix Search List. . . . . . : catapultsystems.com
                                       dmz.catapultsystems.com</pre>
<h5>DNS client configuration</h5>
<p>The <em>Windows IP Configuration</em> section of the output of ipconfig command also shows you the search list of suffixes specified in the DNS client configuration. By default, the <em>DNS Suffix Search List</em> will include only domain suffixes for your own domain. You can change this list using <em>Registry Editor </em>as shown below.</p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://www.olegsych.com/wp-content/uploads/2009/04/image21.png" width="580" height="292" /></p>
<p>Also keep in mind that your domain administrator may be controlling this and other DNS client settings using Active Directory group policy.</p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://www.olegsych.com/wp-content/uploads/2009/04/image22.png" width="580" height="296" /> </p>
<h5>Network adapter configuration</h5>
<p>TCP/IP settings of your network adapter configuration can also provide DNS suffixes for name resolution. As you can see on the screenshot below, you can either specify a connection-specific suffix or an entire list of different DNS suffixes and their order. </p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://www.olegsych.com/wp-content/uploads/2009/04/image23.png" width="574" height="557" /> </p>
<h5>Configuring and verifying DNS name resolution</h5>
<p>As we discussed, DNS client will try to resolve a local host name such as <em>target</em>, by appending the list of domain suffixes it knows about and sending them to the DNS server until it finds a fully-qualified domain name the server can resolve. Unfortunately, this process is complicated by having two different sources of this information on your computer (DNS client configuration and network adapter configuration), different implementations of DNS servers and network administrators controlling these settings through group policy. I had better luck with DNS client configuration and prefer to use it exclusively. However, I can imagine a different combination of these conditions where network adapter configuration may work better. </p>
<p>In our example, where we need to access a host called <em>target</em> located on the Active Directory domain <em>client.lan</em>, use the Registry Editor to add <em>client.lan</em> to beginning of the comma-delimited search list of DNS suffixes. You could also use a registry import file similar to one show below, just make sure you replace the <a href="http://www.catapultsystems.com/">Catapult</a> domain suffixes with your own.</p>
<pre class="code">Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows NT\DNSClient]
&quot;SearchList&quot;=&quot;client.lan,catapultsystems.com,dmz.catapultsystems.com&quot;</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>Once you have configured the list of domain suffixes, verify that your DNS client can resolve target host name using <a href="http://technet.microsoft.com/en-us/library/cc773052.aspx">ping</a> and <a href="http://technet.microsoft.com/en-us/library/cc756097.aspx">nslookup</a> commands as shown below.</p>
<pre class="code">C:\&gt;ping target

Pinging target.client.lan [10.10.4.74] with 32 bytes of data:
Reply from 10.10.4.74: bytes=32 time=2ms TTL=127
Reply from 10.10.4.74: bytes=32 time=1ms TTL=127
Reply from 10.10.4.74: bytes=32 time=1ms TTL=127
Reply from 10.10.4.74: bytes=32 time=1ms TTL=127

Ping statistics for 10.10.4.74:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 1ms, Maximum = 2ms, Average = 1ms

C:\&gt;nslookup target
Server:  dns.client.lan
Address:  10.10.4.6

Name:    target.client.lan
Address:  10.10.4.74</pre>
<p>The <em>nslookup </em>command will tell you if the DNS server is available, if it can resolve the host name and what the local host name was actually resolved to. This step is important to verify that your DNS client guessed the fully-qualified domain name of the target host correctly. Depending on configuration, the DNS client may try using the primary DNS suffix first and ask the server to resolve <em>target.catapultsystems.com</em> before it asks about <em>target.client.lan</em>. Some DNS servers I had to connect to in the past would happily accept these names from other domains and return incorrect IP addresses. </p>
<p>The <em>ping </em>command will tell you if the actual target host is available. Typically computers will respond to ping requests within a local network, but keep in mind that some network administrators may turn this service off to improve security and reduce network traffic.</p>
<p>On rare occasions, the DNS client may not be able to resolve the target host name immediately after you change the configuration. In&#160; this case, you can can give it a nudge by flushing DNS cache and pinging the target host again.</p>
<pre class="code">C:\&gt;ipconfig /flushdns

Windows IP Configuration

Successfully flushed the DNS Resolver Cache.</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<h4>Name resolution through NetBIOS</h4>
<p>With Windows 2000, DNS replaced WINS as a recommended name resolution mechanism. <a href="http://technet.microsoft.com/en-us/library/bb727013.aspx">NetBIOS</a> can work in two modes - <em>peer-to-peer</em>, when name resolution requests are broadcast across the local network, and <em>client-server</em>, when name resolution requests are sent to a NetBIOS Name Service, also known as <a href="http://technet.microsoft.com/en-us/library/bb727015.aspx">WINS</a>. Although many company no longer have WINS servers on their network, you may still be able to use it in peer-to-peer mode. Whether it works will depend on the target host being within the reach for name resolution broadcasts from your computer and having the NetBIOS setting enabled. NetBIOS also works great for name resolution in small home network and virtual networks between several VMs on a single physical host.</p>
<p>In order to use NetBIOS successfully, check the adapter configuration section of the <em>ipconfig</em> output to see whether <em>NetBIOS over Tcpip</em> is <em>Enabled</em> on both your computer and the target host. </p>
<pre class="code">C:\&gt;ipconfig /all

Ethernet adapter Local Area Connection:

   Connection-specific DNS Suffix  . : client.lan
   Description . . . . . . . . . . . : Broadcom NetXtreme 57xx Controller
   Physical Address. . . . . . . . . : 00-11-22-33-44-55
   DHCP Enabled. . . . . . . . . . . : Yes
   Autoconfiguration Enabled . . . . : Yes
   Link-local IPv6 Address . . . . . : fe80::3424:f17e:93ec:8912%11(Preferred)
   IPv4 Address. . . . . . . . . . . : 172.16.242.13(Preferred)
   Subnet Mask . . . . . . . . . . . : 255.255.0.0
   Lease Obtained. . . . . . . . . . : Thursday, April 23, 2009 4:12:45 PM
   Lease Expires . . . . . . . . . . : Thursday, April 30, 2009 4:12:45 PM
   Default Gateway . . . . . . . . . : 172.16.1.2
   DHCP Server . . . . . . . . . . . : 10.10.4.22
   DNS Servers . . . . . . . . . . . : 10.10.4.6
                                       10.10.4.8
   NetBIOS over Tcpip. . . . . . . . : Enabled</pre>
<p>You can change this setting in network adapter configuration as shown below. Note that <em>Default</em> setting for <em>NetBIOS</em> may mean both enabled or disabled. You may want to set it explicitly if you need to use NetBIOS.</p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://www.olegsych.com/wp-content/uploads/2009/04/image24.png" width="567" height="555" /></p>
<p>Having verified that NetBIOS over TCP/IP is enabled, you can use <a href="http://technet.microsoft.com/en-us/library/cc773052.aspx">ping</a> and <a href="http://technet.microsoft.com/en-us/library/cc755486.aspx">nbtstat</a> commands to verify if you can resolve name of the target host through NetBIOS.</p>
<pre class="code">C:\&gt;ping target

Pinging target [172.16.1.195] with 32 bytes of data:
Reply from 172.16.1.195: bytes=32 time=1ms TTL=128
Reply from 172.16.1.195: bytes=32 time=2ms TTL=128
Reply from 172.16.1.195: bytes=32 time=7ms TTL=128
Reply from 172.16.1.195: bytes=32 time=2ms TTL=128

Ping statistics for 172.16.1.195:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 1ms, Maximum = 7ms, Average = 3ms

C:\&gt;nbtstat -r

    NetBIOS Names Resolution and Registration Statistics
    ----------------------------------------------------

    Resolved By Broadcast     = 1
    Resolved By Name Server   = 0

    Registered By Broadcast   = 3
    Registered By Name Server = 0

    NetBIOS Names Resolved By Broadcast
---------------------------------------------
           TARGET       &lt;00&gt;</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p><em>nbtstat</em> will confirm if target host name was resolved through NetBIOS broadcast and <em>ping</em> will confirm if the target host can be reached via TCP/IP. Notice that even though the target host is a member of an Active Directory domain, both ping and nbtstat commands report only its local name. This may be important if the application you are trying to reach on the target host was configured to use fully-qualified domain names.</p>
<h4>Conclusion</h4>
<p>In order to access network resources on a different Active Directory domain, you often need to make additional configuration changes to allow name resolution process to work correctly. Although it is possible to use fully-qualified domain names, such as <em>target.client.lan,</em> or even raw IP addresses, such as 172.16.1.195, many applications are configured to use local host names and will not work correctly. In particular, an application, such as Windows SharePoint Services, may have the local host name embedded in its configuration and will encounter errors after initial successful connection. </p>
<p>In my experience, using DNS-based name resolution and adding the target DNS suffix (<em>client.lan</em>) to the DNS client search list in registry works best. I found DNS client configuration to be more reliable than changing TCP/IP settings of the network adapter. I’ve had situations where DNS suffixes configured through TCP/IP settings would not work no matter what I tried. However, you may have to use network adapter TCP/IP settings if the DNS client configuration is controlled by the Active Directory group policy in your organization. </p>
<p>Although outmoded by DNS in Active Directory networks, NetBIOS-based name resolution is still useful when working on small networks that don’t have Active Directory, such as a home networks or a virtual networks built using Virtual PC and Loopback Adapter. Make sure that NetBIOS over TCP/IP is enabled to take advantage of this name resolution mechanism.</p>
<h4>What’s next</h4>
<p>Once you have name resolution working correctly, your next challenge when accessing network resources is authentication. Majority of applications on the Microsoft platform rely on integrated Windows authentication to allow administrators to manage security in company’s Active Directory. Integrated Windows authentication is a great improvement compared to custom authentication and authorization mechanisms that were prevalent in applications before. Unfortunately, it also creates additional difficulties when you try to access network resources and applications across domain boundaries. In some cases, these difficulties are seemingly insurmountable and lack of knowledge forces us to fall back on older, custom authentication mechanisms, such as SQL Server authentication. However, solutions exist for most of these problems, which is the topic of the next article (coming soon).</p>
<p>&copy;2009 <a href="http://www.olegsych.com">Oleg Sych</a>. All Rights Reserved.</p>.<img src="http://feeds.feedburner.com/~r/olegsych/~4/scSMrOG2kLA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.olegsych.com/2009/04/crossing-domain-boundaries-name-resolution/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.olegsych.com/2009/04/crossing-domain-boundaries-name-resolution/</feedburner:origLink></item>
		<item>
		<title>Simplifying TFS: Applying hot fixes without branching</title>
		<link>http://feedproxy.google.com/~r/olegsych/~3/dBhQaAy5Vjc/</link>
		<comments>http://www.olegsych.com/2009/04/simplifying-tfs-applying-hot-fixes-without-branching/#comments</comments>
		<pubDate>Tue, 14 Apr 2009 21:54:17 +0000</pubDate>
		<dc:creator>Oleg Sych</dc:creator>
		
		<category><![CDATA[Articles]]></category>

		<category><![CDATA[MSBuild]]></category>

		<category><![CDATA[TFS]]></category>

		<category><![CDATA[VSTS]]></category>

		<guid isPermaLink="false">http://www.olegsych.com/2009/04/simplifying-tfs-applying-hot-fixes-without-branching/</guid>
		<description><![CDATA[This article describes an approach for using a Team Foundation workspace to create a hot-fix for a Team build created in the past without introducing untested side effects and without adding complexity of branching and merging the source code.]]></description>
			<content:encoded><![CDATA[</p>
<p>While developing enterprise applications, development teams commonly face a challenge of ongoing development of new features and maintenance of the version already released to production. Consider a team that implements a new feature in April. The new feature goes through testing and gets released to production. The team begins working on the next new feature and starts actively changing code. Then in May, a serious bug is reported by users in production environment. The development team needs to make a hot fix but there is not enough time and not enough resources to put the hot fix through a full test cycle. How can the team make sure that the problem is fixed production without all the changes that were made to implement the new feature for next major version?</p>
<p>A proven approach to solving this problem is to take the snapshot of the source code that was used to compile the version of the application currently in production; make the changes required to fix the problem in this snapshot; build a new version that only contains the bug fixes; concentrate on testing the bug fixes; limit amount of the overall system testing based on available resources and impact of the changes; deploy the hot-fix build to production.</p>
<p>Extensive guidance exists on how to support this scenario using source control functionality in Team Foundation Server. In particular, <a href="http://tfsguide.codeplex.com/">Team Development with Visual Studio Team Foundation Server</a><em></em> (TFS Guide) provides a comprehensive list of strategies in Chapter 5. <a href="http://tfsbranchingguideii.codeplex.com/">TFS 2008 Branching Guide</a> is a more recent set of specific guidelines, consistent with Chapter 5 of the TFS Guide. Here is a set of scenarios TFS Guide defines.</p>
<ul>
<li><em>Scenario 1 – No Branches</em>. Your team works only from the main source tree. In this case, you do not create branches and you do not need isolation. This scenario is generally for small or medium size teams that do not require isolation for teams or for features, and do not need the isolation for releases. </li>
<li><em>Scenario 2 – Branch for Release</em>. Your team creates branches to support an ongoing release. This is the next most common case where you need to create a branch to stabilize for a release. In this case, your team creates a branch before release time to stabilize the release and then merges changes from the release branch back into the main source tree after the software is released. </li>
<li><em>Scenario 3 – Branch for Maintenance</em>. Your team creates a branch to maintain an old build. In this case, you create a branch for your maintenance efforts, so that you do not destabilize your current production builds. You may or may not merge changes from the maintenance branch back into the main tree. For example, you might work on a quick fix for a subset of customers that you do not want to include in the main build. </li>
<li><em>Scenario 4 – Branch for Feature</em>. Your team creates branches based on features. In this case, you create a development branch, perform work in the development branch, and then merge back into your main source tree. You can create separate branches for work on specific features to be completed in parallel. </li>
<li><em>Scenario 5 – Branch for Team</em>. You branch to isolate sub-teams so they can work without being subject to breaking changes, or can work in parallel towards unique milestones. </li>
</ul>
<p>These scenarios provide solid advice that will scale to largest teams and projects. However, we need to keep in mind that there is an immediate overhead associated with multiple branches in the form of the initial learning curve every team member needs to go through as well as ongoing effort required to merge between branches. On a small team where developers work on one project at a time and projects have medium cycle durations (measured in a few months), the need to release hot fixes may arise only occasionally. In scenarios like this, branching approach may be an overkill, causing more problems than it solves. An alternative approach can be used to achieve the goal of releasing a hot fix without having to resort to branching and merging.</p>
<h4>Solution</h4>
<p>With Team Foundation Server, we can rely on <a href="http://msdn.microsoft.com/en-us/library/ms181383.aspx">workspaces</a> to obtain the isolation required to work with a snapshot of the released source code. The idea is to get a labeled snapshot of source code of the production build; make the changes required to fix the problem; check in the modified files; apply a hot-fix label to the files in the workspace; and make Team Build get and build the hot fix version instead of latest. Let’s take a look at these steps in more detail.</p>
<h5>Get source code released to production</h5>
<p>Assuming that development team is already using Team Build, here is how one could get a snapshot of the production source code from source control.</p>
<ul>
<li>In <em>Source Control Explorer</em>, right click root folder of the team project and select <em>Get Specific Version </em>from the context menu. </li>
<li>In the <em>Get </em>dialog, select <em>Label</em> as <em>Version Type </em>and click the […] button to find the label of the build that was released to production. </li>
</ul>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="Get Labeled Version" border="0" alt="Get Labeled Version" src="http://www.olegsych.com/wp-content/uploads/2009/04/image9.png" width="509" height="345" /></p>
<ul>
<li>In the <em>Find Label </em>dialog, select the name of your project in the <em>Project</em> drop-down list and click Find. </li>
</ul>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Find the label of production build" border="0" alt="Find the label of production build" src="http://www.olegsych.com/wp-content/uploads/2009/04/image10.png" width="487" height="312" /></p>
<ul>
<li>Select the appropriate label in the <em>Results </em>list and click <em>Close </em>button. If you have a large number of builds, you may need to limit the scope of search by owner and label name. </li>
<li>Back in the <em>Get </em>dialog, click <em>Get </em>button. Visual Studio will download a snapshot of the code that was compiled by Team Build and released to production. </li>
</ul>
<h5>Make changes required to fix the problem</h5>
<ul>
<li>Before you open your solution, make sure that you don’t have “Get everything when a solution or project is opened” setting turned on. </li>
</ul>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="Turn off &quot;Get everything when a solution or project is opened&quot;" border="0" alt="Turn off &quot;Get everything when a solution or project is opened&quot;" src="http://www.olegsych.com/wp-content/uploads/2009/04/image20.png" width="580" height="338" /></p>
<p>Having downloaded the snapshot of production source code in your workspace, you can now modify it to fix the production problem. You will need to check in the changes you made in order to make them available for Team Build. Note that any changes you check in apply to both current and released version.</p>
<p>In addition to fixing the problem itself, you will also need to modify the Team Build definition. Normally, Team Build will automatically generate a new build number based on the current date. You will need to modify the Team Build definition file to allow overriding build number using MSBuild command-line parameters.</p>
<ul>
<li>Add the following XML to the build definition file. Build definition files are typically called TFSBuild.proj and located in the $/&lt;ProjectName&gt;/TeamBuildTypes/&lt;BuildName&gt; directory of your project in source control. </li>
</ul>
<pre class="code"><span style="color: blue">&lt;!&#8211; </span><span style="color: green">Define property to override default build number  </span><span style="color: blue">&#8211;&gt;
&lt;</span><span style="color: #a31515">PropertyGroup</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">OverrideBuildNumber</span><span style="color: blue">&gt;&lt;/</span><span style="color: #a31515">OverrideBuildNumber</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">PropertyGroup</span><span style="color: blue">&gt;

&lt;!&#8211; </span><span style="color: green">Override automatically generated build number </span><span style="color: blue">&#8211;&gt;
&lt;</span><span style="color: #a31515">Target </span><span style="color: red">Name</span><span style="color: blue">=</span>&quot;<span style="color: blue">BuildNumberOverrideTarget</span>&quot;
        <span style="color: red">Condition</span><span style="color: blue">=</span>&quot;<span style="color: blue">&#8216;$(OverrideBuildNumber)&#8217; != &#8221;</span>&quot;<span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">CreateProperty </span><span style="color: red">Value</span><span style="color: blue">=</span>&quot;<span style="color: blue">$(OverrideBuildNumber)</span>&quot;<span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">Output </span><span style="color: red">TaskParameter</span><span style="color: blue">=</span>&quot;<span style="color: blue">Value</span>&quot; <span style="color: red">PropertyName</span><span style="color: blue">=</span>&quot;<span style="color: blue">BuildNumber</span>&quot; <span style="color: blue">/&gt;
    &lt;/</span><span style="color: #a31515">CreateProperty</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">Target</span><span style="color: blue">&gt;</span></pre>
</p>
<p>Note this fragment defines a custom MSBuild property, <em>OverrideBuildNumber</em>, we will later use to specify the specific hot fix version of source code Team Build needs to compile. It also overrides a standard <a href="http://msdn.microsoft.com/en-us/library/aa395241.aspx">BuildNumberOverrideTarget</a> defined by Team Build to override the automatically generated, <a href="http://blogs.msdn.com/aaronhallberg/archive/2008/02/12/team-build-2008-property-reference.aspx">standard BuildNumber property</a> when <em>OverrideBuildNumber</em> is specified.</p>
<p>Although exact placement of the <em>PropertyGroup</em> and <em>Target </em>elements within the parent <em>Project </em>element inside of TFSBuild.proj shouldn’t matter, it is a good idea to place the <em>OverrideBuildNumber</em> property close to other properties in the beginning of the file, and the <em>Target </em>element close to other tasks in the end of the file. MSBuild files follow the traditional interface/implementation source file layout.</p>
<h5>Apply label to identify the hot fix version of source code</h5>
<p>Normally, Team Build will automatically get the latest version of source code for each build and label it once the build is completed. However, to build a snapshot of the production source code with the hot fix applied, we will need to label it in our <em>workspace</em> first. Team Build will then use this label to download it from source control.</p>
<ul>
<li>Right-click the project root in the Solution Explorer and select Apply Label from the context menu </li>
<li>In the Choose Item Version dialog, select “Workspace Version” and click OK. </li>
</ul>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="Apply label to workspace" border="0" alt="Apply label to workspace" src="http://www.olegsych.com/wp-content/uploads/2009/04/image12.png" width="460" height="406" /> </p>
<ul>
<li>In the Apply Label dialog, enter name of the hot fix label and click OK. </li>
</ul>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="Name label based on the previous production build" border="0" alt="Name label based on the previous production build" src="http://www.olegsych.com/wp-content/uploads/2009/04/image13.png" width="436" height="388" /> </p>
<p>Name of the hot fix label will be typically based on the label of the last production build. In this example, the last production build was labeled as <em>FirstBuild_20090414.<strong>1</strong></em>, so we use <em>FirstBuild_20090414.<strong>2</strong> </em>for the hot-fix build. Although in your case, the numbering scheme may be different, the general idea of incrementing the revision portion of the build number should still apply.</p>
<h5>Make Team Build get and build the hot fix version</h5>
<ul>
<li>Right-click the build in <em>Team Explorer</em> and select <em>Queue New Build</em> item from the context menu. </li>
<li>In the <em>Queue Build </em>dialog, use the “<em>MSBuild command-line arguments</em>” text box to specify values for <em>GetVersion </em>and <em>OverrideBuildNumber</em> properties. </li>
</ul>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="Specify MSBuild command line parameters for the hot-fix build" border="0" alt="Specify MSBuild command line parameters for the hot-fix build" src="http://www.olegsych.com/wp-content/uploads/2009/04/image14.png" width="370" height="431" /> </p>
<p><em>GetVersion</em> is a standard property that specifies which version Team Build needs to pull from source control for the build. It’s value matches format of the <em>VersionSpec</em> parameter of the <a href="http://msdn.microsoft.com/en-us/library/fx7sdeyf.aspx">tf get command</a>. In this example, it needs to be <strong>L</strong><em>LabelName</em>, where (first) <em>L </em>is a required prefix and <em>LabelName</em> is the name of the hot fix label we applied previously. <em>OverrideBuildNumber</em> is the custom property we defined in our <em>TFSBuild.proj</em>.</p>
<ul>
<li>Click the Queue button. </li>
</ul>
<p>Unless there were some error made in <em>TFSBuild.proj </em>or the source code, the build should complete successfully.</p>
<h4>Results </h4>
<p>The sample source code accompanying this article illustrates the Workspace approach. It reflects the following scenario.</p>
<ul>
<li>On April 14, development team delivers a build labeled <em>FirstBuild_20090414.1 </em>to QA team for testing. </li>
<li>On April 15, development team begins actively working on features for the next major version. </li>
<li>On April 28, after a 2 week testing cycle QA team releases build <em>20090414.1</em> to production. </li>
<li>On May 14, a developer checked in implementation of a new feature, scheduled for the next major release. </li>
<li>On May 14, development team delivers a build labeled <em>FirstBuild_20090515.1</em> of the new major version to QA team for testing. </li>
<li>On May&#160; 21, a critical production bug was identified. </li>
<li>On May 21, development team fixes the production problem and delivers a hot fix build labeled <em>FirstBuild_20090414.2 </em>to the QA team for testing. </li>
<li>On May 22, After a 4&#160; hour testing cycle QA team releases hot fix <em>20090414.2 </em>to production. </li>
<li>On May 22, development team resumes working on the new version and delivers new build labeled <em>FirstBuild_20090522.2 </em>to the QA team for testing. </li>
</ul>
<h5>Change History</h5>
<p>Note the changeset numbers shown below. </p>
</p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="Change History" border="0" alt="Change History" src="http://www.olegsych.com/wp-content/uploads/2009/04/image15.png" width="569" height="99" /> </p>
<p>Changeset 220 contains changes for the next major version. In particular, it contains Form1.Designer.cs file, where a new Label was added. Change 221 contains changes required for the hot fix. It contains a modified version of Form1.cs.</p>
<h5>Build History</h5>
<p>Note that the hot fix build 20090414.2 was done after a new feature changes was checked in on 5/14 in changeset 220.</p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="Build History" border="0" alt="Build History" src="http://www.olegsych.com/wp-content/uploads/2009/04/image16.png" width="545" height="256" /> </p>
</p>
<p>Below you can see what got built in the hot fix build 20090414.2. Although Form1.Designer.cs was modified on 5/14 to implement new features, note that this build contains the original version of this file (changeset 218) and new version of Form1.cs (changeset 221), which was modified for the hot fix. </p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Hot fix label" border="0" alt="Hot fix label" src="http://www.olegsych.com/wp-content/uploads/2009/04/image17.png" width="436" height="388" /></p>
<p>And here is what got built in the next regular build <em>20090522.1 </em>of the new version on May 22. Note that it contains new versions of both <em>Form1.Designer.cs </em>(changeset 220) modified earlier and <em>Form1.cs </em>(changeset 221) modified for the hot fix. In other words, changes made for the hot fix were immediately applied to the main codebase of the next major version of the application.</p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Next version label" border="0" alt="Next version label" src="http://www.olegsych.com/wp-content/uploads/2009/04/image18.png" width="436" height="388" /> </p>
<p>Finally, below are the contents of the drop directory. As you can see the drop directory for build <em>20090414.2 </em>was successfully created on <em>5/22 </em>when the build was performed.</p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Team Build drop folders" border="0" alt="Team Build drop folders" src="http://www.olegsych.com/wp-content/uploads/2009/04/image19.png" width="440" height="196" /> </p>
<h4>Conclusion</h4>
<p>Approach described in this article allows to create a hot-fix for a Team Foundation build created in the past without introducing untested side effects and without branching the source code. This approach relies on a TFS workspace to provide temporary isolation of the source code required to apply the hot fix. Because this isolation is temporary, the workspace approach will not work for more complex scenarios, such as when a file where hot fix needs to be made is already modified in the new version or has been renamed. On the other hand, in simple scenarios, where ongoing parallel maintenance of the production version is not necessary, this approach offers a simpler solution that doesn’t impose added complexity of branching and merging on the development team. </p>
<p>The workspace approach can also be combined with the branching approach. The workspace approach could be used to release the initial hot-fix build. The development team can then switch to the branching approach when necessary. In this case, development team would branch the source code based on the label of the last hot-fix build.</p>
<p>Coincidentally, having the <em>OverrideBuildNumber</em> property in your Team Build script also gives you ability to recreate <em>any </em>previous build, not just a special hot-fix build. Imagine going through a long test cycle just to find out that a build you were about to deploy to production was accidentally deleted. Of course, having this ability in your Team Build script is not a substitute for a proper backup procedure. You may not be able to recreate the exact same build output if the Team Build script itself or the Build Server has changed since then.</p>
<h4>Download</h4>
<ul>
<li><a href="http://www.olegsych.com/wp-content/uploads/2009/04/simplifying-tfs-applying-hot-fixes-without-branching.zip">Source code</a> </li>
</ul>
<p>&copy;2009 <a href="http://www.olegsych.com">Oleg Sych</a>. All Rights Reserved.</p>.<img src="http://feeds.feedburner.com/~r/olegsych/~4/dBhQaAy5Vjc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.olegsych.com/2009/04/simplifying-tfs-applying-hot-fixes-without-branching/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.olegsych.com/2009/04/simplifying-tfs-applying-hot-fixes-without-branching/</feedburner:origLink></item>
		<item>
		<title>T4 Editor by Tangible Engineering</title>
		<link>http://feedproxy.google.com/~r/olegsych/~3/KsTamr7NDkw/</link>
		<comments>http://www.olegsych.com/2009/04/t4-editor-by-tangible-engineering/#comments</comments>
		<pubDate>Sat, 11 Apr 2009 23:00:36 +0000</pubDate>
		<dc:creator>Oleg Sych</dc:creator>
		
		<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://www.olegsych.com/2009/04/t4-editor-by-tangible-engineering/</guid>
		<description><![CDATA[Out of the box, code generation files appear and behave as regular text files in the Visual Studio editor. The lack of color syntax highlighting makes working with code generation templates particularly difficult because code blocks and text blocks blend together. Tangible T4 Editor extends the Visual Studio editor to provide color syntax highlighting and IntelliSense for T4 code generation files.]]></description>
			<content:encoded><![CDATA[<h5 style="border-bottom: #f4f4ec 1px solid; border-left: #f4f4ec 1px solid; padding-bottom: 10px; margin: 5px; padding-left: 10px; padding-right: 10px; float: right; border-top: #f4f4ec 1px solid; border-right: #f4f4ec 1px solid; padding-top: 10px"><img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" border="0" src="http://www.olegsych.com/wp-content/themes/gluedideas_subtle/assets/images/icons/tick.png" /> <a href="http://t4-editor.tangible-engineering.com/ModellingTools_teaser.aspx">Download T4 Editor now</a></h5>
<p>Although Visual Studio 2008 includes <a href="http://www.olegsych.com/2007/12/text-template-transformation-toolkit/">T4</a>, a fully-featured, template-based code generation engine, its support for editing of the code generation templates is very limited. Out of the box, code generation files appear and behave as regular text files in the Visual Studio editor. Not only does this means that you don’t have IntelliSense we have come to take for granted in the last 10 years, you also don’t have the color syntax highlighting which became a standard feature in IDEs 20 years ago. The lack of color syntax highlighting makes working with code generation templates particularly difficult because <a href="http://www.olegsych.com/2008/02/t4-statement-blocks/">code blocks</a> and <a href="http://www.olegsych.com/2008/02/t4-text-blocks/">text blocks</a> blend together and make it hard to distinguish code that will be executed during code generation from the code that will be generated.</p>
<p><a href="http://www.olegsych.com/wp-content/uploads/2009/06/animated.gif"><img style="border-bottom: #f4f4ec 1px solid; border-left: #f4f4ec 1px solid; display: block; float: none; margin-left: auto; border-top: #f4f4ec 1px solid; margin-right: auto; border-right: #f4f4ec 1px solid; margine: none" title="Template Editing in Visual Studio" border="0" alt="Template Editing in Visual Studio" src="http://www.olegsych.com/wp-content/uploads/2009/06/animated-thumb.gif" width="450" height="310" /></a> </p>
<p>In order to take full advantage of the productivity offered by T4 and template-based code generation, you really need to have a modern design-time support in your IDE. Enter the <a href="http://t4-editor.tangible-engineering.com/">T4 Editor</a> by <a href="http://www.tangible-engineering.com">Tangible Engineering</a>.</p>
<h4>T4 Editor Features</h4>
<p>Tangible T4 Editor extends the Visual Studio editor to provide color syntax highlighting and IntelliSense for T4 code generation files. There are too many features to describe in a blog post, but here are some of my favorites.</p>
<h5><img style="border-right-width: 0px; margin: 0px 0px 0px 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Color Syntax Highlighting" border="0" alt="Color Syntax Highlighting" align="right" src="http://www.olegsych.com/wp-content/uploads/2009/04/image2.png" width="278" height="160" />Color syntax highlighting</h5>
<p>The color palette is very close to ASP.NET. A nice improvement is a subtle yellow background for code blocks that&#160; helps you distinguish template code from the generated code. You get colors in both code blocks (based on the language specified in <a href="http://www.olegsych.com/2008/02/t4-template-directive/">template directive</a>) and text blocks (based on extension specified in <a href="http://www.olegsych.com/2008/02/t4-output-directive/">output directive</a>).</p>
<h5><img style="border-right-width: 0px; margin: 0px 5px 0px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Intelliprompt for T4 directives and code blocks" border="0" alt="Intelliprompt for T4 directives and code blocks" align="left" src="http://www.olegsych.com/wp-content/uploads/2009/04/image3.png" width="289" height="158" />IntelliPrompt for T4 directives and code blocks</h5>
<p>As soon as you type &lt;, the editor displays a list of T4 directives and code blocks, helping you type them. If you select or type &lt;#@, the editor will display a list of standard T4 directives. Once you select the directive, the editor displays prompts for each parameter, helping you along each step of the way.</p>
<h5><img style="border-right-width: 0px; margin: 0px 0px 0px 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="IntelliPrompt and IntelliSense for template code" border="0" alt="IntelliPrompt and IntelliSense for template code" align="right" src="http://www.olegsych.com/wp-content/uploads/2009/04/image4.png" width="282" height="172" />IntelliPrompt and IntelliSense for template code</h5>
<p>When editing template code in code blocks, the editor displays list of class members for a variable as soon as you type period. Once you select a particular method, the editor will display a hint with method signature. Placing text caret on an opening curly brace highlights it and its closing counterpart with green back color, helping you to locate it across text blocks that may be between them.</p>
<h5><img style="border-right-width: 0px; margin: 0px 5px 0px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Support for included T4 files" border="0" alt="Support for included T4 files" align="left" src="http://www.olegsych.com/wp-content/uploads/2009/04/image5.png" width="310" height="165" />Support for included T4 files</h5>
<p>The editor also provides IntelliSense for included T4 files. Pointing cursor at the <em>DatabaseProject </em>of the <em>LinqToSqlGenerator </em>class included via <em>LinqToSql.tt</em> displays the documentation comments! This is extremely helpful when working with <a href="http://www.codeplex.com/t4toolbox">T4 Toolbox</a> templates that use included files extensively.</p>
<h4>Conclusion</h4>
<p>There is a lot more to the Tangible T4 Editor than would be practical to describe here. I have focused only on those features that help me in my daily work and intentionally left out the UML modeling tools Tangible provides together with the T4 Editor. These modeling tools can be used for building custom code generators as well.</p>
<p>If you are working with T4, I would definitely recommend for you to check it out. The guys at Tangible Engineering work hard to make their T4 Editor compatible with the T4 Toolbox and support complex, composite code generators.</p>
<p>The editor comes in two editions - free and professional. The free edition limits the IntelliSense to a small subset of core .NET assemblies. This version would be appropriate for developer primarily using the T4 code generators created by others. The professional version provides IntelliSense for all assemblies referenced by a T4 code generator and enables strongly typed access to the models created by Tangible modeling tools. Developers who routinely customize or create new T4 code generators will benefit from the additional productivity features offered by the professional edition.</p>
<h4>Links</h4>
<ul>
<li>T4 Editor: <a title="http://t4-editor.tangible-engineering.com" href="http://t4-editor.tangible-engineering.com">http://t4-editor.tangible-engineering.com</a> </li>
<li>Tangible Engineering: <a title="http://www.tangible-engineering.com" href="http://www.tangible-engineering.com">http://www.tangible-engineering.com</a> </li>
</ul>
<p>&copy;2009 <a href="http://www.olegsych.com">Oleg Sych</a>. All Rights Reserved.</p>.<img src="http://feeds.feedburner.com/~r/olegsych/~4/KsTamr7NDkw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.olegsych.com/2009/04/t4-editor-by-tangible-engineering/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.olegsych.com/2009/04/t4-editor-by-tangible-engineering/</feedburner:origLink></item>
		<item>
		<title>T4Toolbox build 9.3.21.1 problem</title>
		<link>http://feedproxy.google.com/~r/olegsych/~3/vGJEsoqdgeg/</link>
		<comments>http://www.olegsych.com/2009/03/t4toolbox-build-93211-problem/#comments</comments>
		<pubDate>Thu, 26 Mar 2009 12:22:34 +0000</pubDate>
		<dc:creator>Oleg Sych</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.olegsych.com/2009/03/t4toolbox-build-93211-problem/</guid>
		<description><![CDATA[There is a serious problem in version 9.3.21.1 of the T4 Toolbox. In this version installer was modified to deploy T4Toolbox.dll assembly in the GAC, but unexpectedly it stopped installing it into the regular location - $(ProgramFiles)\T4 Toolbox\bin. It turned out to be an expected behavior of Microsoft Installer, as Aaron Stebner describes here. Following [...]]]></description>
			<content:encoded><![CDATA[<p>There is a <a href="http://t4toolbox.codeplex.com/WorkItem/View.aspx?WorkItemId=12869">serious problem</a> in version 9.3.21.1 of the <a href="http://www.codeplex.com/t4toolbox">T4 Toolbox</a>. In this version installer was modified to deploy T4Toolbox.dll assembly in the GAC, but unexpectedly it stopped installing it into the regular location - $(ProgramFiles)\T4 Toolbox\bin. It turned out to be an expected behavior of Microsoft Installer, as Aaron Stebner describes <a href="http://blogs.msdn.com/astebner/archive/2005/06/24/432521.aspx">here</a>. Following Aaron’s suggestion, I changed the installer to deploy T4Toolbox.dll in two different components - one for GAC and the other for the Bin folder. Luckily, it didn’t require using custom actions, thanks to <a href="http://robmensching.com/blog/posts/2007/6/1/quotSmart-cabbingquot-added-to-WiX-toolset">“smart cabbing” implemented by the WiX team</a>.</p>
<p>The problem is now fixed in the new version <a href="http://t4toolbox.codeplex.com/Release/ProjectReleases.aspx">9.3.21.2</a> of the T4 Toolbox. Special thanks to <a href="http://www.danielfortunov.com/software">Daniel Fortunov</a>, <a href="http://rohancragg.co.uk/">Rohan Cragg</a> and <a href="http://www.codeplex.com/site/users/contact/stebrennan?OriginalUrl=http%3a%2f%2fwww.codeplex.com%2fsite%2fusers%2fview%2fstebrennan">stebrennan</a> for reporting and helping to troubleshoot the error. </p>
<p>&copy;2009 <a href="http://www.olegsych.com">Oleg Sych</a>. All Rights Reserved.</p>.<img src="http://feeds.feedburner.com/~r/olegsych/~4/vGJEsoqdgeg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.olegsych.com/2009/03/t4toolbox-build-93211-problem/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.olegsych.com/2009/03/t4toolbox-build-93211-problem/</feedburner:origLink></item>
		<item>
		<title>T4 Toolbox: Generating files in different folders and projects</title>
		<link>http://feedproxy.google.com/~r/olegsych/~3/B1O-F55pr0k/</link>
		<comments>http://www.olegsych.com/2009/03/t4-toolbox-generating-files-in-different-folders-and-projects/#comments</comments>
		<pubDate>Sat, 21 Mar 2009 15:27:38 +0000</pubDate>
		<dc:creator>Oleg Sych</dc:creator>
		
		<category><![CDATA[Articles]]></category>

		<category><![CDATA[Code Generation]]></category>

		<category><![CDATA[T4]]></category>

		<category><![CDATA[Visual Studio]]></category>

		<category><![CDATA[VSTS]]></category>

		<guid isPermaLink="false">http://www.olegsych.com/2009/03/t4-toolbox-generating-files-in-different-folders-and-projects/</guid>
		<description><![CDATA[This article describes how to generate multiple output files in different directories and different folders with the help of version 9.3.21.1 of T4 Toolbox.]]></description>
			<content:encoded><![CDATA[<p>As scope and complexity of a code generator increases, as the number of files and file types it produces grows, it may become desirable or even necessary to save these output files to different folders in a Visual Studio project or even different projects in a Visual Studio solution. Consider models, like LINQ to SQL, that allow us to design both application and database parts of an information system. When generating code from such a model, it may be beneficial to place generated <a href="http://msdn.microsoft.com/en-us/library/system.data.linq.datacontext.aspx">DataContext</a> class in a <a href="http://en.wikipedia.org/wiki/Data_access_layer">data access layer</a> project, entity classes in a <a href="http://en.wikipedia.org/wiki/Business_logic_layer">business logic layer</a> project and SQL schema scripts in a database project of your Visual Studio solution. This scenario is also frequent in frameworks, like <a href="http://code.google.com/p/sharp-architecture">S#arp Architecture</a>, that provide code generators to create project structure scaffolding for developers to use as a starting point.</p>
<p>To accomplish this task in a T4 code generator today, we would have to place a separate T4 file in each folder where one or more output files need to be generated. This approach may be feasible, however it increases the number of code generation files you need to maintain and leads to errors when developers forget to regenerate one of many files after changing the model it uses. In addition to this, not all types of projects in Visual Studio currently support T4. Most notably, Database projects of <a href="http://msdn.microsoft.com/en-us/teamsystem/dd408380.aspx">VSTS Development edition</a> don’t support custom tools and thus don’t allow using T4. It would be ideal to have a single T4 code generation file per model that creates all required output files in various folders and projects. However, this approach presents several major challenges.</p>
<p>Automation model for newer types of Visual Studio projects is implemented in .NET and cannot be accessed from <a href="http://www.olegsych.com/2008/05/t4-architecture/">T4 code running in templating AppDomain</a> directly. Instead, the T4 code generator has to pass information about output files, their locations and target projects to the main <a href="http://msdn.microsoft.com/en-us/library/system.appdomain.aspx">AppDomain</a> of Visual Studio and execute the code that updates Visual Studio solution and projects there.</p>
<p>Managing a set of output files saved in different folders and different projects also becomes more difficult. In order to automatically remove previously generated output files that are no longer necessary, <a href="http://www.olegsych.com/2008/03/how-to-generate-multiple-outputs-from-single-t4-template/">we store the list of all generated files in the Visual Studio project</a> that contains the T4 file. The generated files are stored as “DependentUpon” the T4 file that generated them and appear as nested items under the T4 file in the Solution Explorer. This approach doesn’t work for files in other folders because Visual Studio project model doesn&#8217;t support nested items in different folders or nested links. Instead, the T4 code generator has to store the list of generated output files in a separate file.</p>
<p>Detailed discussion of these problems and available solutions is outside of scope of this article and probably outside of reader’s interest. <a href="http://t4toolbox.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=24272"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Sample Solution" border="0" alt="Sample Solution" align="right" src="http://www.olegsych.com/wp-content/uploads/2009/03/image.png" width="226" height="287" />Version 9.3.21.1</a> of <a href="http://www.codeplex.com/t4toolbox">T4 Toolbox</a> provides support for generating output files in different folders and different projects of Visual Studio solution. Complete details can be found in the source code on <a href="http://www.codeplex.com/">CodePlex</a>.</p>
<h4>Usage</h4>
<ul>
<li>Download and install the latest version of T4 Toolbox from <a href="http://t4toolbox.codeplex.com/Release/ProjectReleases.aspx">CodePlex</a>. </li>
<li>Create a Visual Studio solution with two C# Class Library projects - <em>ClassLibrary1.csproj </em>and <em>ClassLibrary2.csproj</em>. </li>
<li>Add a new code generation file called <em>CodeGenerator.tt</em> to the first class library project. </li>
<li>Modify contents of the new file to look like so: </li>
</ul>
<pre class="code"><span style="background: gold">&lt;#@</span><span style="color: red"> </span><span style="color: brown">template </span><span style="color: red">language=</span>&quot;<span style="color: blue">C#</span>&quot; <span style="color: red">hostspecific=</span>&quot;<span style="color: blue">True</span>&quot; <span style="color: red">debug=</span>&quot;<span style="color: blue">True</span>&quot; <span style="background: gold">#&gt;
&lt;#@</span><span style="color: red"> </span><span style="color: brown">output </span><span style="color: red">extension=</span>&quot;<span style="color: blue">txt</span>&quot; <span style="background: gold">#&gt;
&lt;#@</span><span style="color: red"> </span><span style="color: brown">include </span><span style="color: red">file=</span>&quot;<span style="color: blue">T4Toolbox.tt</span>&quot; <span style="background: gold">#&gt;
&lt;#
</span><span style="background: #f0f8ff; color: #191970">    SampleTemplate template = new SampleTemplate();
    template.Output.File = @&quot;SubFolder</span>\<span style="background: #f0f8ff; color: #191970">SampleOutput.txt&quot;;
    template.Output.Project = @&quot;..\ClassLibrary2</span>\<span style="background: #f0f8ff; color: #191970">ClassLibrary2.csproj&quot;;
    template.Render();
</span><span style="background: gold">#&gt;
&lt;#+
</span><span style="background: #f0f8ff; color: #191970">    public class SampleTemplate : Template
    {
        protected override void RenderCore()
        {
            this.WriteLine(&quot;Hello, World!&quot;);
        }
    }
</span><span style="background: gold">#&gt;</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<ul>
<li>Notice that a new output file called <em>SampleOutput.txt </em>was generated in a folder called <em>SubFolder</em> of the second class library project, <em>ClassLibrary2.csproj</em>. </li>
<li>Also notice that a log file, <em>CodeGenerator.tt.log</em> was generated under <em>CodeGenerator.tt</em>. This file contains a list of all output files produced by last successful transformation and looks like so: </li>
</ul>
<pre class="code">// &lt;autogenerated&gt;
//   This file contains the list of files generated by CodeGenerator.tt.
//   ...
// &lt;/autogenerated&gt;
..\ClassLibrary2\SubFolder\SampleOutput.txt
.\CodeGenerator.tt.log</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<h4>Analysis</h4>
<p>The first thing we need to review is the new <em>Output </em>property of the <em>Template </em>base class. It gets an object of type <em>OutputInfo</em> which defines the output file that will be produced by the template. <em>OutputInfo </em>currently has three properties - <em>File</em>, <em>Project</em> and <em>Encoding</em>.</p>
<h5>OutputInfo.Project</h5>
<p>This property is of type <a href="http://msdn.microsoft.com/en-us/library/system.string.aspx">String</a>. You can set this property to specify the Visual Studio project where output file will be generated. Its value can be a relative path, in which case T4 Toolbox will resolve it based on the location of the <em><a href="http://msdn.microsoft.com/en-us/library/Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost.TemplateFile.aspx">TemplateFile</a></em> being transformed, <em>CodeGenerator.tt</em> in the example above. The target project must be loaded in the current Visual Studio solution, or an error will be reported. By default, <em>Project</em> property is empty, which is interpreted as “the project that contains the <em><a href="http://msdn.microsoft.com/en-us/library/Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost.TemplateFile.aspx">TemplateFile</a>&#160;</em>being transformed” (<em>ClassLibrary1 </em>in the example above).</p>
<h5>OutputInfo.File</h5>
<p>This property is of type <a href="http://msdn.microsoft.com/en-us/library/system.string.aspx">String</a>. You can set this property to specify the file where output of the template will be stored. Its value can be a relative path, in which case T4 Toolbox will resolve it based on the location of the target project (see <em>OutputInfo.Project</em> above). By default, <em>File</em> property is empty, which means “standard output file of the <em><a href="http://msdn.microsoft.com/en-us/library/Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost.TemplateFile.aspx">TemplateFile</a>&#160;</em>being transformed” (<em>CodeGenerator.txt </em>in the example above). If <em>File </em>property contains only a file name without directory, the output file will be added as a nested project item under the main template file (<em>CodeGenerator.tt</em> in the example above).</p>
<h5>OutputInfo.Encoding</h5>
<p>This property is of type <a href="http://msdn.microsoft.com/en-us/library/system.text.encoding.aspx">Encoding</a>. You can set this property to specify encoding of the output file the template will produce. This is an equivalent of the <em>encoding </em>parameter of standard <a href="http://www.olegsych.com/2008/02/t4-output-directive/">output directive</a> provided by T4 which works for individual output files.</p>
<h5>Template.Render()</h5>
<p>Behavior of the <em>Template.Render </em>method now depends on the <em>Output</em> properties. By default, when <em>Output.Project</em> and <em>Output.File</em> are empty, <em>Render </em>adds output of the template to the standard output file, like it did in the previous versions of the toolbox.</p>
<h5>Template.RenderToFile()</h5>
<p><em>RenderToFile</em> method has now become a convenience shortcut that sets <em>Output.File</em> and calls <em>Render</em> in a single statement<em>.</em></p>
<h5>Code generation log</h5>
<p>Code generation log (<em>CodeGenerator.tt.log</em>) is created when at least one output file is generated in a different folder or a different project than the main <em>TemplateFile</em>. If all output files are generated in the same folder and the same project as the main <em>TemplateFile</em>, the list of generated output files is stored as a set of project items nested under it, like it did in the previous version.</p>
<h4>Your feedback</h4>
<p>Special thanks go to <a href="http://www.jeffreylodell.com/">Jeff Odell</a>, <a href="http://gcapnias.spaces.live.com/">George Capnias</a> and <a href="http://devlicio.us/blogs/billy_mccafferty">Billy McCaferty</a> who provided their feedback on early versions of this functionality. Its design and implementation are based primarily on usage scenarios in the T4 Toolbox itself. It was a challenging process, requiring several tradeoffs. There is no feasible way for us to conduct usability studies, so your feedback will be very important in validating these decisions. Please give the new version a try and share your experience with us:</p>
<ul>
<li>Is the code easy to write? </li>
<li>Does the code work as you would expect? </li>
<li>Is the code intuitive? </li>
</ul>
<p>Here are some design aspects we need your feedback on.</p>
<h5>Template.Output property</h5>
<p><em>Template.Output.File</em> started as a simple <em>Template.OutputFile</em> property of type <a href="http://msdn.microsoft.com/en-us/library/system.string.aspx">String</a>. <em>OutputInfo</em> class and <em>Template.Output</em> property was created when we realized that there will be multiple attributes that will apply an output file. We felt that adding these additional attributes as properties to the <em>Template </em>class would pollute its interface and make concrete <em>Template </em>classes more difficult to use. As a result, we now have <em>Output </em>property which gets an object and have to write assignment statements with two periods in a chain just to assign output file or output project.</p>
<h5>Relative Path Resolution</h5>
<p>Relative path to <em>Output.Project</em> is resolved based on the location of the main <a href="http://msdn.microsoft.com/en-us/library/Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost.TemplateFile.aspx">TemplateFile</a>. However, relative path to <em>Output.File</em> is resolved based on the location of the <em>Output.Project</em>. Initially, both paths were resolved relative to the location of the main <a href="http://msdn.microsoft.com/en-us/library/Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost.TemplateFile.aspx">TemplateFile</a>. This feels logical and intuitive in a simple example where you have just one template. However, in a scenario with a complex directory structure and multiple templates such when generating SQL schema files in a VSTS Database project, the folder structure defined by <em>Output.File</em> doesn’t need to change based on <em>Output.Project</em>. In this case, it felt redundant having to write extra code for each <em>Output.File</em> in addition to simply changing <em>Output.Project</em>.</p>
<h5>Code generation log</h5>
<p>The initial goal was to continue storing the list of generated output files as nested items in the project that contains the main <em>TemplateFile</em>. Unfortunately, it appears to be impossible in the current Visual Studio project model to store links to files in other locations as nested project items under the main <em>TemplateFile</em>. The second choice was to store the log in standard output file of the main template and avoid having to create an extra file. However, Visual Studio overwrites the standard output file when there is a compilation error in the main template, which would obliterate your code generation log if you forget a semicolon at the end of the line and could result in dozens of orphaned output files in your solution. This is why we create code generation log as a separate file. Can you think of a better way to do this?</p>
<h4>Download</h4>
<ul>
<li><a href="http://t4toolbox.codeplex.com/Release/ProjectReleases.aspx">T4 Toolbox version 9.3.21.1</a> </li>
</ul>
<p>&copy;2009 <a href="http://www.olegsych.com">Oleg Sych</a>. All Rights Reserved.</p>.<img src="http://feeds.feedburner.com/~r/olegsych/~4/B1O-F55pr0k" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.olegsych.com/2009/03/t4-toolbox-generating-files-in-different-folders-and-projects/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.olegsych.com/2009/03/t4-toolbox-generating-files-in-different-folders-and-projects/</feedburner:origLink></item>
		<item>
		<title>T4 Tutorial: Making code generators extensible</title>
		<link>http://feedproxy.google.com/~r/olegsych/~3/5grPN4oYv-I/</link>
		<comments>http://www.olegsych.com/2009/02/t4-tutorial-making-code-generators-extensible/#comments</comments>
		<pubDate>Thu, 12 Feb 2009 23:00:00 +0000</pubDate>
		<dc:creator>Oleg Sych</dc:creator>
		
		<category><![CDATA[Articles]]></category>

		<category><![CDATA[C#]]></category>

		<category><![CDATA[Code Generation]]></category>

		<category><![CDATA[SMO]]></category>

		<category><![CDATA[SQL]]></category>

		<category><![CDATA[T4]]></category>

		<category><![CDATA[Visual Studio]]></category>

		<guid isPermaLink="false">http://www.olegsych.com/2009/02/t4-tutorial-making-code-generators-extensible/</guid>
		<description><![CDATA[This article illustrates how authors can use proven object-oriented principles and design patterns to make their code generators extensible and allow users to customize code generators without having to modify and maintain third-party code.]]></description>
			<content:encoded><![CDATA[<p>This article is a part of a series that introduces code generation with C# and <a href="http://www.olegsych.com/2007/12/text-template-transformation-toolkit/">Text Templates</a> (also known as T4 Templates) in Visual Studio; explains how to create reusable templates and combine them in complex code generators. In order to follow examples in this article, you need to have Visual Studio 2008 Standard Edition or higher, SQL Server 2008, <a href="http://www.codeplex.com/t4toolbox">T4 Toolbox</a> and <a href="http://www.olegsych.com/2009/04/t4-editor-by-tangible-engineering">T4 Editor</a> installed on your computer.</p>
<h4>Introduction</h4>
<p>When different developers or teams use the same code generator on different projects, it is likely that they will want to generate code differently. Consider the CRUD stored procedure generator we created <a href="http://www.olegsych.com/2008/11/t4-tutorial-unit-testing-code-generators/">previously</a>. Here is a DELETE stored procedure it generates for Orders table in the Northwind sample database.</p>
<pre class="code"><span style="color: blue">create procedure </span>Orders_Delete
    @OrderID <span style="color: blue">int
as
    delete from </span>Orders
    <span style="color: blue">where
        </span>OrderID = @OrderID</pre>
<p>Note that this T-SQL code will successfully create the stored procedure if it doesn&#8217;t exist. However, it will fail if the stored procedure has already been created. In order to handle both scenarios, we would need to change this code to look like this.</p>
<pre class="code"><span style="color: blue">if  </span><span style="color: gray">exists (</span><span style="color: blue">select </span><span style="color: gray">* </span><span style="color: blue">from </span><span style="color: green">sys.objects
            </span><span style="color: blue">where </span><span style="color: magenta">object_id </span><span style="color: gray">= </span><span style="color: magenta">object_id</span><span style="color: gray">(</span><span style="color: red">&#8216;Orders_Delete&#8217;</span><span style="color: gray">)
              and </span><span style="color: blue">type </span><span style="color: gray">in (</span><span style="color: red">&#8216;P&#8217;</span><span style="color: gray">, </span><span style="color: red">&#8216;PC&#8217;</span><span style="color: gray">))
    </span><span style="color: blue">drop procedure </span>Orders_Delete
go 

<span style="color: blue">create procedure </span>Orders_Delete
    @OrderID <span style="color: blue">int
as
    delete from </span>Orders
    <span style="color: blue">where
        </span>OrderID <span style="color: gray">= </span>@OrderID</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>Although the new T-SQL file will handle both scenarios, the extra code it now contains is not necessary if you are using <a href="http://msdn.microsoft.com/en-us/vsts2008/db/default.aspx">Database edition</a> of Visual Studio Team System. The Database edition automatically generates different deployment scripts depending on the current schema in the target database. This additional code would only add extra code and complexity to the database project, making it not only unnecessary but undesirable.</p>
<p>Let&#8217;s assume that author of the original generator of CRUD stored procedures was targeting the Database edition of Visual Studio and did not implement code that drops existing procedures. How would a developer who doesn’t have the Database edition add this capability to the code generator?</p>
<p>It is always possible to simply modify code of the original generator to make it work the exact way you need it. However, by modifying the code someone else produced, you are taking on the responsibility of maintaining it. If you need to use a newer version of the original generator, you will have to re-implement your customizations in the new version of its code. For small code generators or short-term projects, this may be a valid approach. However, modifying complex code generators in a long-term project may significantly increase the effort required to maintain it over time. Luckily, we can use proven object-oriented design techniques such as inheritance and encapsulation to allow customizing code generators without resorting to hacking their source code.</p>
<h4>Using virtual methods to make templates extensible</h4>
<p>Here is an abbreviated version of template that generates delete stored procedure in the original CRUD generator.</p>
<pre class="code"><span style="background: gold">&lt;#+
</span><span style="background: #f0f8ff; color: #191970">public class DeleteProcedureTemplate : Template
{
    public string DatabaseName;
    public string TableName; 

    protected override void RenderCore()
    {
        // &#8230;
</span><span style="background: gold">#&gt;
</span><span style="color: gray">create procedure </span><span style="background: gold">&lt;#=</span><span style="background: #f0f8ff; color: #191970"> this.TableName </span><span style="background: gold">#&gt;</span><span style="color: gray">_Delete
</span><span style="background: gold">&lt;#+
</span><span style="background: #f0f8ff; color: #191970">        // &#8230;
</span><span style="background: gold">#&gt;
</span><span style="color: gray">as
    delete from </span><span style="background: gold">&lt;#=</span><span style="background: #f0f8ff; color: #191970"> this.TableName </span><span style="background: gold">#&gt;
</span><span style="color: red">    </span><span style="color: gray">where
</span><span style="background: gold">&lt;#+
</span><span style="background: #f0f8ff; color: #191970">        // &#8230;</span><span style="background: #f0f8ff; color: #191970">
    }
}
</span><span style="background: gold">#&gt;</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>Notice that <em>RenderCore</em> method is virtual. We can change its behavior by creating a descendant class and overriding the method like so:</p>
<pre class="code"><span style="background: gold">&lt;#+
</span><span style="background: #f0f8ff; color: #191970">class MyDeleteProcedureTemplate: DeleteProcedureTemplate
{
    protected override void RenderCore()
    {
</span><span style="background: gold">#&gt;
</span><span style="color: gray">if  exists (select * from sys.objects
            where object_id = object_id(&#8217;</span><span style="background: gold">&lt;#=</span><span style="background: #f0f8ff; color: #191970"> this.TableName </span><span style="background: gold">#&gt;</span><span style="color: gray">_Delete&#8217;)
              and type in (&#8217;P', &#8216;PC&#8217;))
    drop procedure </span><span style="background: gold">&lt;#=</span><span style="background: #f0f8ff; color: #191970"> this.TableName </span><span style="background: gold">#&gt;</span><span style="color: gray">_Delete
go
</span><span style="background: gold">&lt;#+
</span><span style="background: #f0f8ff; color: #191970">        base.RenderCore();
    }
}
</span><span style="background: gold">#&gt;</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>Now we only need to replace the original template before running the CRUD generator in <em>NorthwindProcedures.tt</em>.</p>
<pre class="code"><span style="background: gold">&lt;#
</span><span style="background: #f0f8ff; color: #191970">    CrudProcedureGenerator generator = new CrudProcedureGenerator();
    generator.DeleteTemplate = new MyDeleteProcedureTemplate();
    generator.DatabaseName = &#8220;Northwind&#8221;;
    generator.Run();
</span><span style="background: gold">#&gt;
</span></pre>
<p>In other words, we have changed behavior of a third-party code generator defined in <em>CrudProcedureGenerator.tt</em> and <em>DeleteProcedureTemplate.tt</em> without directly modifying the third-party source code. All of our customizations are made in <em>NorthwindProcedures.tt</em>, which is a source file in our project. When new version of the CRUD generator becomes available, we can simply replace the older source files and our customizations will continue to work.</p>
<p>We can repeat these steps to override behavior of the <em>InsertProcedureTemplate </em>and <em>UpdateProcedureTemplate</em>. Completed working source code is available for download at the bottom of this article.</p>
<h4>Conclusion</h4>
<p>The customization described in this article was made possible by two important aspects of our CRUD generator design. First, generation of each type of stored procedures is encapsulated in a separate <em>Template</em> class with a virtual <em>RenderCore</em> method we could override. Second,  the generator class exposed templates as public fields, allowing us to replace individual templates without having to modify or override the generator. This design is a form of <a href="http://en.wikipedia.org/wiki/Strategy_pattern">Strategy pattern</a>, with template classes serving as <em>Strategies</em> and generator playing the role of <em>Context</em>.</p>
<p>In simple scenarios, when a single <em>Template</em> generates a single logical unit of code, such as a stored procedure, it is sufficient to simply place the code generation logic inside of the overridden <em>RenderCore</em> method. In more complex scenarios, a <em>Template</em> may generate multiple units of code, such as a C# class with multiple methods and properties. To allow users to customize generation of a particular unit of code without having to reimplement the entire <em>RenderCore, </em>consider creating a separate virtual method to generate each logical unit of code and calling it from the <em>RenderCore </em>method. This approach helps authors to reduce the size and complexity of the <em>RenderCore </em>method and also allows the users to override these virtual methods individually. This design is a form of <a href="http://en.wikipedia.org/wiki/Template_Method">Template Method pattern</a>, with <em>RenderCore </em>serving as <em>Template Method</em>.</p>
<p>In the next article in the tutorial series, we will review some of the additional features the <a href="http://www.codeplex.com/t4toolbox">T4 Toolbox</a> framework provides for code generator extensibility, such as conditional code generation and output redirection.</p>
<h4>Download</h4>
<ul>
<li><a href="http://www.olegsych.com/wp-content/uploads/2008/11/t4-tutorial-unit-testing-code-generators.zip">Source code, initial</a></li>
<li><a href="http://www.olegsych.com/wp-content/uploads/2009/02/t4-tutorial-making-code-generators-extensible.zip">Source code, completed</a></li>
</ul>
<p>&copy;2009 <a href="http://www.olegsych.com">Oleg Sych</a>. All Rights Reserved.</p>.<img src="http://feeds.feedburner.com/~r/olegsych/~4/5grPN4oYv-I" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.olegsych.com/2009/02/t4-tutorial-making-code-generators-extensible/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.olegsych.com/2009/02/t4-tutorial-making-code-generators-extensible/</feedburner:origLink></item>
	</channel>
</rss>
