<?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" version="2.0">

<channel>
	<title>Oleg Sych</title>
	<link>http://www.olegsych.com</link>
	<description>Interfaces are like alcohol - they are a lot of fun when used in moderation.</description>
	<pubDate>Mon, 27 Feb 2012 15:23:59 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.3.3</generator>
	<language>en</language>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.olegsych.com/olegsych" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="olegsych" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><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" /><item>
		<title>.Config File Transformation</title>
		<link>http://www.olegsych.com/2010/12/config-file-transformation/</link>
		<comments>http://www.olegsych.com/2010/12/config-file-transformation/#comments</comments>
		<pubDate>Mon, 20 Dec 2010 02:32:12 +0000</pubDate>
		<dc:creator>Oleg Sych</dc:creator>
		
		<category><![CDATA[Articles]]></category>

		<category><![CDATA[.NET]]></category>

		<category><![CDATA[Azure]]></category>

		<category><![CDATA[Code Generation]]></category>

		<category><![CDATA[MSBuild]]></category>

		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://www.olegsych.com/2010/12/config-file-transformation/</guid>
		<description><![CDATA[This article provides an overview of configuration files in .NET applications, discusses common problems of managing environment-specific settings, reviews different approaches for managing configuration files and introduces .config file transformation in Visual Studio 2010.  The downloadable code example and shows how to use it not only with web application projects, but also with regular app.config files.]]></description>
			<content:encoded><![CDATA[<p>This article provides an overview of configuration files in .NET applications, discusses common problems of managing environment-specific settings, reviews different approaches for managing configuration settings and introduces .config file transformation in Visual Studio 2010.&#160; The downloadable code example and shows how to use config transforms not only with web applications, but also with regular app.config files in other types of projects.</p>
<h4>Overview of Configuration Files</h4>
<p>Today, most non-trivial applications use configuration settings. Commercial software products must be able to run in different environments for different users. At the very least that means being able to run from a folder specified by the user during installation. Non-trivial applications often need dozens of settings, including database connection strings, network locations and credentials. These configuration settings can be stored and accessed in a number of different ways. On the Microsoft Windows platforms, we have used INI files, database tables and registry keys. Applications built using the .NET Framework commonly use <a href="http://msdn.microsoft.com/en-us/library/ms229689.aspx" target="_blank">XML-based configuration files</a>, such as the one shown below.</p>
<h6>App.config</h6>
<pre class="code"><span style="color: blue">&lt;?</span><span style="color: #a31515">xml </span><span style="color: red">version</span><span style="color: blue">=</span>&quot;<span style="color: blue">1.0</span>&quot; <span style="color: red">encoding</span><span style="color: blue">=</span>&quot;<span style="color: blue">utf-8</span>&quot; <span style="color: blue">?&gt;
&lt;</span><span style="color: #a31515">configuration</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">appSettings</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">add </span><span style="color: red">key</span><span style="color: blue">=</span>&quot;<span style="color: blue">MySetting</span>&quot; <span style="color: red">value</span><span style="color: blue">=</span>&quot;<span style="color: blue">MyValue</span>&quot;<span style="color: blue">/&gt;
  &lt;/</span><span style="color: #a31515">appSettings</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">configuration</span><span style="color: blue">&gt;</span></pre>
<p>When building a C# or Visual Basic project that contains this configuration file, Visual Studio will copy it to the output directory and rename to match the name of the executable, such as <em>ConsoleApplication.exe.config</em>. The application can access the settings from this file using <a href="http://msdn.microsoft.com/en-us/library/system.configuration.configurationmanager.aspx" target="_blank">ConfigurationManager</a> and other classes in the <a href="http://msdn.microsoft.com/en-us/library/system.configuration.aspx" target="_blank">System.Configuration</a> namespace. Here is an example. </p>
<pre class="code"><span style="color: blue">using </span>System;
<span style="color: blue">using </span>System.Configuration;

<span style="color: blue">namespace </span>ConsoleApplication
{
    <span style="color: blue">class </span><span style="color: #2b91af">Program
    </span>{
        <span style="color: blue">static void </span>Main(<span style="color: blue">string</span>[] args)
        {
            <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #2b91af">ConfigurationManager</span>.AppSettings[<span style="color: #a31515">&quot;MySetting&quot;</span>]);
            <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">&quot;Press any key to close the application &#8230;&quot;</span>);
            <span style="color: #2b91af">Console</span>.ReadKey();
        }
    }
}</pre>
<h4>Managing Configuration Settings</h4>
<p>Although applications developed by companies for <i>internal</i> use may not need to be as configurable, mature development teams take advantage of configuration settings to run their applications in different environments for development and production purposes so that the application can be modified and tested without affecting the real users. Because internal applications are typically installed and configured by people with technical background who are comfortable with editing the XML-based configuration files, building a robust <a href="http://en.wikipedia.org/wiki/Graphical_user_interface" target="_blank">GUI</a> for configuration settings does not add much business value. However, the task of configuring the application for a particular environment still remains and falls onto the plate of either developers or administrators. When done manually this process is tedious and error-prone. </p>
<h5>Multiple .Config Files</h5>
<p>Without resorting to writing an installation program or script, one of the options you have is to maintain a separate copy of the application configuration file for each environment. For example, in addition to the App.config shown above which you would use in development environment, you might also have two more configuration files for your test and production environments.</p>
<h6>Test.config</h6>
<pre class="code"><span style="color: blue">&lt;?</span><span style="color: #a31515">xml </span><span style="color: red">version</span><span style="color: blue">=</span>&quot;<span style="color: blue">1.0</span>&quot; <span style="color: red">encoding</span><span style="color: blue">=</span>&quot;<span style="color: blue">utf-8</span>&quot; <span style="color: blue">?&gt;
&lt;</span><span style="color: #a31515">configuration</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">appSettings</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">add </span><span style="color: red">key</span><span style="color: blue">=</span>&quot;<span style="color: blue">MySetting</span>&quot; <span style="color: red">value</span><span style="color: blue">=</span>&quot;<span style="color: blue">MyTestValue</span>&quot;<span style="color: blue">/&gt;
  &lt;/</span><span style="color: #a31515">appSettings</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">configuration</span><span style="color: blue">&gt;</span></pre>
<h6>Production.config</h6>
<pre class="code"><span style="color: blue">&lt;?</span><span style="color: #a31515">xml </span><span style="color: red">version</span><span style="color: blue">=</span>&quot;<span style="color: blue">1.0</span>&quot; <span style="color: red">encoding</span><span style="color: blue">=</span>&quot;<span style="color: blue">utf-8</span>&quot; <span style="color: blue">?&gt;
&lt;</span><span style="color: #a31515">configuration</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">appSettings</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">add </span><span style="color: red">key</span><span style="color: blue">=</span>&quot;<span style="color: blue">MySetting</span>&quot; <span style="color: red">value</span><span style="color: blue">=</span>&quot;<span style="color: blue">MyProductionValue</span>&quot;<span style="color: blue">/&gt;
  &lt;/</span><span style="color: #a31515">appSettings</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">configuration</span><span style="color: blue">&gt;</span></pre>
<p>When deploying the application to test environment, you would replace the default <em>ConsoleApplication.exe.config</em> with the <em>Test.config</em>, and for production environment you would use the <em>Production.config</em>. The process is simple enough to perform manually and easy to automate with a simple batch script. However, it only works well when the configuration file is small and contains only environment-specific settings, such as database connection strings. As configuration files become larger maintaining the common settings duplicated in each configuration file becomes more and more difficult. </p>
<h5>ConfigSource Attribute</h5>
<p>To solve this problem, the .NET Framework 2.0 introduced <a href="http://msdn.microsoft.com/en-us/library/system.configuration.sectioninformation.configsource.aspx" target="_blank">ConfigSource</a> attribute for all configuration sections. Using this attribute we can extract environment-specific sections from the App.config to a separate file. </p>
<h6>App.config</h6>
<pre class="code"><span style="color: blue">&lt;?</span><span style="color: #a31515">xml </span><span style="color: red">version</span><span style="color: blue">=</span>&quot;<span style="color: blue">1.0</span>&quot; <span style="color: red">encoding</span><span style="color: blue">=</span>&quot;<span style="color: blue">utf-8</span>&quot; <span style="color: blue">?&gt;
&lt;</span><span style="color: #a31515">configuration</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">appSettings </span><span style="color: red">configSource</span><span style="color: blue">=</span>&quot;<span style="color: blue">AppSettings.config</span>&quot;<span style="color: blue">/&gt;
&lt;/</span><span style="color: #a31515">configuration</span><span style="color: blue">&gt;</span></pre>
<h6>AppSettings.config</h6>
<pre class="code"><span style="color: blue">&lt;?</span><span style="color: #a31515">xml </span><span style="color: red">version</span><span style="color: blue">=</span>&quot;<span style="color: blue">1.0</span>&quot; <span style="color: red">encoding</span><span style="color: blue">=</span>&quot;<span style="color: blue">utf-8</span>&quot; <span style="color: blue">?&gt;
&lt;</span><span style="color: #a31515">appSettings</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">add </span><span style="color: red">key</span><span style="color: blue">=</span>&quot;<span style="color: blue">MySetting</span>&quot; <span style="color: red">value</span><span style="color: blue">=</span>&quot;<span style="color: blue">MyValue</span>&quot;<span style="color: blue">/&gt;
&lt;/</span><span style="color: #a31515">appSettings</span><span style="color: blue">&gt;</span></pre>
<p>When a section file, such as <em>AppSettings.config,</em> is copied to the output directory, <em>ConfigurationManager</em> will be able to automatically load settings from it instead of the main configuration file, <em>ConsoleApplication.exe.config </em>in our example. To change this configuration for a particular environment, we now only need to replace the section file, <em>AppSettings.config</em>, and not the entire <em>App.config</em>. Here are the environment-specific versions of the section configuration files for our sample project.</p>
<h6>AppSettings.Test.config</h6>
<pre class="code"><span style="color: blue">&lt;?</span><span style="color: #a31515">xml </span><span style="color: red">version</span><span style="color: blue">=</span>&quot;<span style="color: blue">1.0</span>&quot; <span style="color: red">encoding</span><span style="color: blue">=</span>&quot;<span style="color: blue">utf-8</span>&quot; <span style="color: blue">?&gt;
&lt;</span><span style="color: #a31515">appSettings</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">add </span><span style="color: red">key</span><span style="color: blue">=</span>&quot;<span style="color: blue">MySetting</span>&quot; <span style="color: red">value</span><span style="color: blue">=</span>&quot;<span style="color: blue">MyTestValue</span>&quot;<span style="color: blue">/&gt;
&lt;/</span><span style="color: #a31515">appSettings</span><span style="color: blue">&gt;</span></pre>
<h6>AppSettings.Production.config</h6>
<pre class="code"><span style="color: blue">&lt;?</span><span style="color: #a31515">xml </span><span style="color: red">version</span><span style="color: blue">=</span>&quot;<span style="color: blue">1.0</span>&quot; <span style="color: red">encoding</span><span style="color: blue">=</span>&quot;<span style="color: blue">utf-8</span>&quot; <span style="color: blue">?&gt;
&lt;</span><span style="color: #a31515">appSettings</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">add </span><span style="color: red">key</span><span style="color: blue">=</span>&quot;<span style="color: blue">MySetting</span>&quot; <span style="color: red">value</span><span style="color: blue">=</span>&quot;<span style="color: blue">MyProductionValue</span>&quot;<span style="color: blue">/&gt;
&lt;/</span><span style="color: #a31515">appSettings</span><span style="color: blue">&gt;</span></pre>
<p>Extracting sections into separate files allows us to manage settings at a more granular level. It works well when environment-specific settings are concentrated in a particular section, such as <em>AppSettings</em> or <em>ConnectionStrings</em>. However, once the number of sections that need to be replaced for different environments begins to grow, the section files become more and more difficult to manage. </p>
<h4>Web.config File Transformation </h4>
<p>Visual Studio 2010 introduced a new solution for managing environment-specific settings in Web application projects – <a href="http://msdn.microsoft.com/en-us/library/dd394698.aspx#webconfig_transformation" target="_blank">config file transformation</a>. With this approach, your web.config file stores settings required to run the application in your local development environment.</p>
<h6>Web.config</h6>
<pre class="code"><span style="color: blue">&lt;?</span><span style="color: #a31515">xml </span><span style="color: red">version</span><span style="color: blue">=</span>&quot;<span style="color: blue">1.0</span>&quot; <span style="color: red">encoding</span><span style="color: blue">=</span>&quot;<span style="color: blue">utf-8</span>&quot; <span style="color: blue">?&gt;
&lt;</span><span style="color: #a31515">configuration</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">appSettings</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">add </span><span style="color: red">key</span><span style="color: blue">=</span>&quot;<span style="color: blue">MySetting</span>&quot; <span style="color: red">value</span><span style="color: blue">=</span>&quot;<span style="color: blue">Debug Value</span>&quot;<span style="color: blue">/&gt;
  &lt;/</span><span style="color: #a31515">appSettings</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">configuration</span><span style="color: blue">&gt;</span></pre>
<p><a href="http://www.olegsych.com/wp-content/uploads/2010/12/image2.png"><img style="background-image: none; border-right-width: 0px; margin: ; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" align="right" src="http://www.olegsych.com/wp-content/uploads/2010/12/image-thumb2.png" width="216" height="133" /></a>On the other hand, all settings specific to a particular shared environment (such as test, staging or production) are stored in a separate transformation file.The example below shows a transformation file for the <em>Release </em>environment that changes <em>MySetting</em> defined in the <em>Web.config</em>.</p>
<h5>Web.Release.config</h5>
<pre class="code"><span style="color: blue">&lt;?</span><span style="color: #a31515">xml </span><span style="color: red">version</span><span style="color: blue">=</span>&quot;<span style="color: blue">1.0</span>&quot;<span style="color: blue">?&gt;
</span><span style="color: blue">&lt;</span><span style="color: #a31515">configuration </span><span style="color: red">xmlns:xdt</span><span style="color: blue">=</span>&quot;<span style="color: blue">http://schemas.microsoft.com/XML-Document-Transform</span>&quot;<span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">appSettings</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">add </span><span style="color: red">key</span><span style="color: blue">=</span>&quot;<span style="color: blue">MySetting</span>&quot; <span style="color: red">value</span><span style="color: blue">=</span>&quot;<span style="color: blue">Release Value</span>&quot;
         <span style="color: red">xdt:Transform</span><span style="color: blue">=</span>&quot;<span style="color: blue">SetAttributes</span>&quot; <span style="color: red">xdt:Locator</span><span style="color: blue">=</span>&quot;<span style="color: blue">Match(key)</span>&quot;<span style="color: blue">/&gt;
  &lt;/</span><span style="color: #a31515">appSettings</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">configuration</span><span style="color: blue">&gt;</span></pre>
<p><a href="http://www.olegsych.com/wp-content/uploads/2010/12/image3.png"><img style="background-image: none; border-right-width: 0px; margin: 0px 0px 0px 5px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" align="right" src="http://www.olegsych.com/wp-content/uploads/2010/12/image-thumb3.png" width="327" height="140" /></a>Visual Studio updates Web.Config using the transformation file when packaging or publishing the application. You can perform both of these actions from the project’s context menu in Solution Explorer or using MSBuild to build the <em>Package </em>target of the web application project.</p>
<pre class="code">msbuild WebApplication.csproj /target:Package /p:Configuration=Release</pre>
<p>New web application projects you create in Visual Studio 2010 will have both Debug and Release transform files created automatically. If you have an existing web application project, perhaps upgraded from Visual Studio 2008, you can add transform files to it by right-clicking the web.config in the Solution Explorer and selecting “Add Config Transforms” from the context menu. However, keep in mind that config transformation does not occur during regular build or debugging of the web application project. If <em>Debug</em> configuration represents local development environment, you may want to remove the <em>Web.Debug.config</em> transformation file to avoid confusion.</p>
<p><a href="http://msdn.microsoft.com/en-us/library/dd465326.aspx" target="_blank">Transformation file syntax</a> is based on the standard syntax of configuration files, with addition of the <em>xdt</em> attributes, such as <em>Locator</em>, which specifies how to find a particular setting in the original .config file, and <em>Transform</em>, which specifies how to modify it. In our example, the <em>add</em> element will be found in the <em>appSettings </em>section using its <em>key </em>(<em>MySetting</em>); once the original element is found, all of its attributes will be replaced with those specified in the transformation file (<em>SetAttributes</em>). Here is the resulting <em>Web.config </em>after transformation.</p>
<h6>Web.config (transformed)</h6>
<pre class="code"><span style="color: blue">&lt;?</span><span style="color: #a31515">xml </span><span style="color: red">version</span><span style="color: blue">=</span>&quot;<span style="color: blue">1.0</span>&quot; <span style="color: red">encoding</span><span style="color: blue">=</span>&quot;<span style="color: blue">utf-8</span>&quot;<span style="color: blue">?&gt;
&lt;</span><span style="color: #a31515">configuration</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">appSettings</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">add </span><span style="color: red">key</span><span style="color: blue">=</span>&quot;<span style="color: blue">MySetting</span>&quot; <span style="color: red">value</span><span style="color: blue">=</span>&quot;<span style="color: blue">Debug Value</span>&quot;<span style="color: blue">/&gt;
  &lt;/</span><span style="color: #a31515">appSettings</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">configuration</span><span style="color: blue">&gt;</span></pre>
<p>Unlike the approach based on <em>ConfigSource</em> attribute and separate section files, you only have a single transform file per environment. And because config transformation is integrated in the web application publishing process and allows you to use standard Visual Studio build configurations, such as <em>Debug</em> for development and <em>Release</em> for production, as well as define custom environments, such as <em>Test</em>, as necessary. Configurations/environments can be switched quickly, without leaving Visual Studio or running external tools.</p>
<p><a href="http://www.olegsych.com/wp-content/uploads/2010/12/image.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.olegsych.com/wp-content/uploads/2010/12/image-thumb.png" width="553" height="154" /></a></p>
<p>On the flipside, in order to use config transforms you need to learn a new XML-based language that defines the transformations. However, you will typically use a minimum subset of its capabilities and find that, on most internal application projects, the initial effort will be well justified by the simplicity and reduced cost of ongoing maintenance of the environment-specific settings.</p>
<h4>App.config File Transformation</h4>
<p>Out of the box, .config file transformation is only available for Web application projects in Visual Studio 2010. Console, WinForms, WPF and other applications projects don’t support this capability out of the box. Luckily, you can add it to any Visual Basic or C# project by manually changing the project source file as shown below.</p>
<pre class="code"><span style="color: blue">&lt;!&#8211; </span><span style="color: green">&#8230; </span><span style="color: blue">&#8211;&gt;
&lt;</span><span style="color: #a31515">Import </span><span style="color: red">Project</span><span style="color: blue">=</span>&quot;<span style="color: blue">$(MSBuildToolsPath)\Microsoft.CSharp.targets</span>&quot; <span style="color: blue">/&gt;

&lt;</span><span style="color: #a31515">UsingTask </span><span style="color: red">TaskName</span><span style="color: blue">=</span>&quot;<span style="color: blue">TransformXml</span>&quot;
  <span style="color: red">AssemblyFile</span><span style="color: blue">=</span>&quot;<span style="color: blue">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll</span>&quot; <span style="color: blue">/&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">AfterCompile</span>&quot; <span style="color: red">Condition</span><span style="color: blue">=</span>&quot;<span style="color: blue">exists(&#8217;app.$(Configuration).config&#8217;)</span>&quot;<span style="color: blue">&gt;
  &lt;!&#8211; </span><span style="color: green">Generate transformed app config in the intermediate directory </span><span style="color: blue">&#8211;&gt;
  &lt;</span><span style="color: #a31515">TransformXml </span><span style="color: red">Source</span><span style="color: blue">=</span>&quot;<span style="color: blue">app.config</span>&quot;
    <span style="color: red">Destination</span><span style="color: blue">=</span>&quot;<span style="color: blue">$(IntermediateOutputPath)$(TargetFileName).config</span>&quot;
    <span style="color: red">Transform</span><span style="color: blue">=</span>&quot;<span style="color: blue">app.$(Configuration).config</span>&quot; <span style="color: blue">/&gt;
  &lt;!&#8211; </span><span style="color: green">Force build process to use the transformed configuration file from now on. </span><span style="color: blue">&#8211;&gt;
  &lt;</span><span style="color: #a31515">ItemGroup</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">AppConfigWithTargetPath </span><span style="color: red">Remove</span><span style="color: blue">=</span>&quot;<span style="color: blue">app.config</span>&quot;<span style="color: blue">/&gt;
    &lt;</span><span style="color: #a31515">AppConfigWithTargetPath </span><span style="color: red">Include</span><span style="color: blue">=</span>&quot;<span style="color: blue">$(IntermediateOutputPath)$(TargetFileName).config</span>&quot;<span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">TargetPath</span><span style="color: blue">&gt;</span>$(TargetFileName).config<span style="color: blue">&lt;/</span><span style="color: #a31515">TargetPath</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">AppConfigWithTargetPath</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">ItemGroup</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">Target</span><span style="color: blue">&gt;
&lt;!&#8211; </span><span style="color: green">&#8230; </span><span style="color: blue">&#8211;&gt;
</span></pre>
<p>In this MSBuild code snippet, we are using the <em>TransformXml </em>task defined in the <em>Microsoft.Web.Publishing.Tasks.dll</em>. This is the task responsible for transforming Web.config files in Web application projects. It takes parameters that specify names of the original .config file, the transform file and the output (transformed) file. We use <em>TransformXml </em>task to override <em>AfterCompile</em> target if a transform file exist for the current build configuration. For example, if our project contains a file called <em>App.Debug.config </em>and the current project configuration is <em>Debug</em>, the <em>AfterCompile </em>target will be called. Finally, we use <em>ItemGroup</em> element to change the built-in <em>AppConfigWithTargetPath</em> item collection. This is necessary in order for the <a href="http://msdn.microsoft.com/en-us/library/t71a733d.aspx" target="_blank">ClickOnce</a> publishing process and the Visual Studio debugging process (vshost.exe) to discover and use the transformed configuration file instead of the original one.</p>
<p><a href="http://www.olegsych.com/wp-content/uploads/2010/12/image4.png"><img style="background-image: none; border-right-width: 0px; margin: 0px 0px 0px 5px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" align="right" src="http://www.olegsych.com/wp-content/uploads/2010/12/image-thumb4.png" width="210" height="111" /></a> </p>
<p>Unlike with Web application projects, you will need to add the transform files to the project manually, following the naming convention of <em><strong>App.&lt;Configuration Name&gt;.config</strong></em>, such as <em>App.Release.config</em>. Also, the transform files will not be automatically nested under the main App.config. To achieve this effect, you can manually edit the project file and specify the <a href="http://msdn.microsoft.com/en-us/library/bb629388.aspx" target="_blank">DependentUpon</a> attribute for transform files as shown below.</p>
<pre class="code"><span style="color: blue">&lt;!&#8211; </span><span style="color: green">&#8230; </span><span style="color: blue">&#8211;&gt;
&lt;</span><span style="color: #a31515">ItemGroup</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">None </span><span style="color: red">Include</span><span style="color: blue">=</span>&quot;<span style="color: blue">App.config</span>&quot; <span style="color: blue">/&gt;
</span><span style="color: blue">  &lt;</span><span style="color: #a31515">None </span><span style="color: red">Include</span><span style="color: blue">=</span>&quot;<span style="color: blue">App.Release.config</span>&quot;<span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">DependentUpon</span><span style="color: blue">&gt;</span>App.config<span style="color: blue">&lt;/</span><span style="color: #a31515">DependentUpon</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">None</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">ItemGroup</span><span style="color: blue">&gt;
&lt;!&#8211; </span><span style="color: green">&#8230; </span><span style="color: blue">&#8211;&gt;</span></pre>
<p>With these changes made, the App.config file will be transformed at build time, using the configuration-specific transformation file you provided. If the transformation file doesn’t exist, the original App.config file will be used. Unlike web applications, which are compiled at run-time by ASP.NET, regular applications are fully compiled by Visual Studio during project build. This also means that config transformation occurs during development build/debug cycle, so if the <em>Debug</em> project configuration represents local environment on each developer’s machine, you <em>could</em> use config transformation for <em>Debug</em> configuration too. However, for consistency with web projects and to reduce confusion for less experienced developers on your team, it may be best to avoid this.</p>
<h4>XML File Transformation</h4>
<p>Config transformation is not limited to only .NET configuration files. You can transform any valid XML files in Visual Studio projects based on MSBuild, such as <a href="http://www.microsoft.com/windowsazure/getstarted/" target="_blank">Windows Azure Project</a>. This project type comes with Windows Azure tools for Visual Studio and is used to build <a href="http://msdn.microsoft.com/en-us/library/dd179341.aspx" target="_blank">service packages</a> that describe one or more virtual machines (called roles) and include the compiled applications that will be running on these machines. Each service package is accompanied by a service configuration file, which is typically used to specify connection strings for SQL Azure databases and storage accounts as well as the number of virtual machine instances required for each role. </p>
<h6>ServiceConfiguration.cscfg (Production)</h6>
<pre class="code"><span style="color: blue">&lt;?</span><span style="color: #a31515">xml </span><span style="color: red">version</span><span style="color: blue">=</span>&quot;<span style="color: blue">1.0</span>&quot; <span style="color: red">encoding</span><span style="color: blue">=</span>&quot;<span style="color: blue">utf-8</span>&quot;<span style="color: blue">?&gt;
&lt;</span><span style="color: #a31515">ServiceConfiguration </span><span style="color: red">serviceName</span><span style="color: blue">=</span>&quot;<span style="color: blue">WindowsAzureProject</span>&quot; <span style="color: red">osFamily</span><span style="color: blue">=</span>&quot;<span style="color: blue">1</span>&quot; <span style="color: red">osVersion</span><span style="color: blue">=</span>&quot;<span style="color: blue">*</span>&quot;
  <span style="color: red">xmlns</span><span style="color: blue">=</span>&quot;<span style="color: blue">http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration</span>&quot;<span style="color: blue">&gt;

  &lt;</span><span style="color: #a31515">Role </span><span style="color: red">name</span><span style="color: blue">=</span>&quot;<span style="color: blue">WebApplication</span>&quot;<span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">Instances </span><span style="color: red">count</span><span style="color: blue">=</span>&quot;<span style="color: blue">2</span>&quot; <span style="color: blue">/&gt;
    &lt;</span><span style="color: #a31515">ConfigurationSettings</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">Setting </span><span style="color: red">name</span><span style="color: blue">=</span>&quot;<span style="color: blue">Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString</span>&quot;
        <span style="color: red">value</span><span style="color: blue">=</span>&quot;<span style="color: blue">DefaultEndpointsProtocol=https;AccountName=&#8230;;AccountKey=&#8230;</span>&quot; <span style="color: blue">/&gt;
    &lt;/</span><span style="color: #a31515">ConfigurationSettings</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">Role</span><span style="color: blue">&gt;

&lt;/</span><span style="color: #a31515">ServiceConfiguration</span><span style="color: blue">&gt;
</span></pre>
<p>As you might expect, Visual Studio also provides the ability to debug Windows Azure Projects on your local machine, without uploading the service package to the cloud. When running in local development environment, called Dev Fabric, your service package often needs to have different configuration. For example, instead of connecting to a SQL Azure database it would connect to your local SQL Server instance, instead of cloud-based table storage it would write diagnostic logs to the local storage emulator, instead of having 2 or more role instances required for high-availability it would need to run only one to improve debugging experience, and so on. Here is a development version of the service configuration file you might want to use. </p>
<h6>ServiceConfiguration.cscfg (Debug)</h6>
<pre class="code"><span style="color: blue">&lt;?</span><span style="color: #a31515">xml </span><span style="color: red">version</span><span style="color: blue">=</span>&quot;<span style="color: blue">1.0</span>&quot; <span style="color: red">encoding</span><span style="color: blue">=</span>&quot;<span style="color: blue">utf-8</span>&quot;<span style="color: blue">?&gt;
&lt;</span><span style="color: #a31515">ServiceConfiguration </span><span style="color: red">serviceName</span><span style="color: blue">=</span>&quot;<span style="color: blue">WindowsAzureProject</span>&quot; <span style="color: red">osFamily</span><span style="color: blue">=</span>&quot;<span style="color: blue">1</span>&quot; <span style="color: red">osVersion</span><span style="color: blue">=</span>&quot;<span style="color: blue">*</span>&quot;
  <span style="color: red">xmlns</span><span style="color: blue">=</span>&quot;<span style="color: blue">http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration</span>&quot;<span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">Role </span><span style="color: red">name</span><span style="color: blue">=</span>&quot;<span style="color: blue">WebApplication</span>&quot;<span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">Instances </span><span style="color: red">count</span><span style="color: blue">=</span>&quot;<span style="color: blue">1</span>&quot; <span style="color: blue">/&gt;
    &lt;</span><span style="color: #a31515">ConfigurationSettings</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">Setting </span><span style="color: red">name</span><span style="color: blue">=</span>&quot;<span style="color: blue">Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString</span>&quot;
        <span style="color: red">value</span><span style="color: blue">=</span>&quot;<span style="color: blue">UseDevelopmentStorage=true</span>&quot; <span style="color: blue">/&gt;
    &lt;/</span><span style="color: #a31515">ConfigurationSettings</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">Role</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">ServiceConfiguration</span><span style="color: blue">&gt;
</span></pre>
<p><a href="http://www.olegsych.com/wp-content/uploads/2010/12/image5.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px 0px 0px 5px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" align="right" src="http://www.olegsych.com/wp-content/uploads/2010/12/image-thumb5.png" width="278" height="132" /></a>With a little customization we can get config transformation work for the Windows Azure Projects too. Since Visual Studio doesn’t support config transformation for this type of projects yet, we again need to modify it manually as shown below.</p>
<h6>WindowsAzureProject.ccproj</h6>
<pre class="code"><span style="color: blue">&lt;!&#8211; </span><span style="color: green">&#8230; </span><span style="color: blue">&#8211;&gt;
&lt;</span><span style="color: #a31515">Import </span><span style="color: red">Project</span><span style="color: blue">=</span>&quot;<span style="color: blue">$(CloudExtensionsDir)Microsoft.CloudService.targets</span>&quot; <span style="color: blue">/&gt;

&lt;</span><span style="color: #a31515">UsingTask </span><span style="color: red">TaskName</span><span style="color: blue">=</span>&quot;<span style="color: blue">TransformXml</span>&quot;
  <span style="color: red">AssemblyFile</span><span style="color: blue">=</span>&quot;<span style="color: blue">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll</span>&quot; <span style="color: blue">/&gt;

&lt;</span><span style="color: #a31515">PropertyGroup</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">ServiceConfigurationTransform</span><span style="color: blue">&gt;</span>ServiceConfiguration.$(Configuration).cscfg<span style="color: blue">&lt;/</span><span style="color: #a31515">ServiceConfigurationTransform</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">PropertyGroup</span><span style="color: blue">&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">TransformServiceConfiguration</span>&quot;
  <span style="color: red">BeforeTargets</span><span style="color: blue">=</span>&quot;<span style="color: blue">CopyServiceDefinitionAndConfiguration</span>&quot;
  <span style="color: red">Condition</span><span style="color: blue">=</span>&quot;<span style="color: blue">exists(&#8217;$(ServiceConfigurationTransform)&#8217;)</span>&quot;<span style="color: blue">&gt;

  &lt;!&#8211; </span><span style="color: green">Generate transformed service config in the intermediate directory </span><span style="color: blue">&#8211;&gt;
  &lt;</span><span style="color: #a31515">TransformXml </span><span style="color: red">Source</span><span style="color: blue">=</span>&quot;<span style="color: blue">@(ServiceConfiguration)</span>&quot;
    <span style="color: red">Destination</span><span style="color: blue">=</span>&quot;<span style="color: blue">$(IntermediateOutputPath)%(Filename)%(Extension)</span>&quot;
    <span style="color: red">Transform</span><span style="color: blue">=</span>&quot;<span style="color: blue">$(ServiceConfigurationTransform)</span>&quot; <span style="color: blue">/&gt;

  &lt;!&#8211; </span><span style="color: green">Force build process to use the transformed configuration file from now on. </span><span style="color: blue">&#8211;&gt;
  &lt;</span><span style="color: #a31515">ItemGroup</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">ServiceConfiguration </span><span style="color: red">Remove</span><span style="color: blue">=</span>&quot;<span style="color: blue">ServiceConfiguration.cscfg</span>&quot; <span style="color: blue">/&gt;
    &lt;</span><span style="color: #a31515">ServiceConfiguration </span><span style="color: red">Include</span><span style="color: blue">=</span>&quot;<span style="color: blue">$(IntermediateOutputPath)ServiceConfiguration.cscfg</span>&quot; <span style="color: blue">/&gt;
  &lt;/</span><span style="color: #a31515">ItemGroup</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">Target</span><span style="color: blue">&gt;
&lt;!&#8211; </span><span style="color: green">&#8230; </span><span style="color: blue">&#8211;&gt;
</span></pre>
<p>Just like with the console application we customized previously, we use the <em>TransformXml</em> MSBuild task defined in the <em>Microsoft.Web.Publishing.Tasks.dll</em> to transform the service configuration file in a custom target called <em>TransformServiceConfiguration</em> that will be executed before the built-in <em>CopyServiceDefinitionAndConfiguration.</em> One the transformed configuration file is generated in the intermediate (<em>obj</em>) output directory, we force the build process to use it instead of the original one. </p>
<h6>WindowsAzureProject.ccproj</h6>
<pre class="code"><span style="color: blue">&lt;!&#8211; </span><span style="color: green">Items for the project </span><span style="color: blue">&#8211;&gt;
&lt;</span><span style="color: #a31515">ItemGroup</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">ServiceDefinition </span><span style="color: red">Include</span><span style="color: blue">=</span>&quot;<span style="color: blue">ServiceDefinition.csdef</span>&quot; <span style="color: blue">/&gt;
  &lt;</span><span style="color: #a31515">ServiceConfiguration </span><span style="color: red">Include</span><span style="color: blue">=</span>&quot;<span style="color: blue">ServiceConfiguration.cscfg</span>&quot; <span style="color: blue">/&gt;
  &lt;</span><span style="color: #a31515">None </span><span style="color: red">Include</span><span style="color: blue">=</span>&quot;<span style="color: blue">ServiceConfiguration.Release.cscfg</span>&quot;<span style="color: blue">/&gt;
&lt;/</span><span style="color: #a31515">ItemGroup</span><span style="color: blue">&gt;</span></pre>
<p>We also need to add the transform file to our project by manually changing the project file as shown above. Unlike C# and VB projects, Windows Azure Projects in the 1.3 version of the Azure Tools for Visual Studio don’t support the <em>DependentUpon</em> metadata and we can’t make the transform files nested under the configuration file in Solution Explorer. Here is the transformation file that changes our debug version of the service configuration to match the production version shown above.</p>
<h6>ServiceConfiguration.Release.cscfg</h6>
<pre class="code"><span style="color: blue">&lt;?</span><span style="color: #a31515">xml </span><span style="color: red">version</span><span style="color: blue">=</span>&quot;<span style="color: blue">1.0</span>&quot; <span style="color: red">encoding</span><span style="color: blue">=</span>&quot;<span style="color: blue">utf-8</span>&quot;<span style="color: blue">?&gt;
&lt;</span><span style="color: #a31515">sc:ServiceConfiguration
  </span><span style="color: red">xmlns:sc</span><span style="color: blue">=</span>&quot;<span style="color: blue">http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration</span>&quot;
  <span style="color: red">xmlns:xdt</span><span style="color: blue">=</span>&quot;<span style="color: blue">http://schemas.microsoft.com/XML-Document-Transform</span>&quot;<span style="color: blue">&gt;

  &lt;</span><span style="color: #a31515">sc:Role </span><span style="color: red">name</span><span style="color: blue">=</span>&quot;<span style="color: blue">WebApplication</span>&quot; <span style="color: red">xdt:Locator</span><span style="color: blue">=</span>&quot;<span style="color: blue">Match(name)</span>&quot;<span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">sc:Instances </span><span style="color: red">count</span><span style="color: blue">=</span>&quot;<span style="color: blue">2</span>&quot; <span style="color: red">xdt:Transform</span><span style="color: blue">=</span>&quot;<span style="color: blue">SetAttributes</span>&quot;<span style="color: blue">/&gt;
    &lt;</span><span style="color: #a31515">sc:ConfigurationSettings</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">sc:Setting </span><span style="color: red">name</span><span style="color: blue">=</span>&quot;<span style="color: blue">Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString</span>&quot;
        <span style="color: red">value</span><span style="color: blue">=</span>&quot;<span style="color: blue">DefaultEndpointsProtocol=https;AccountName=youraccount;AccountKey=yourkey</span>&quot;
        <span style="color: red">xdt:Transform</span><span style="color: blue">=</span>&quot;<span style="color: blue">SetAttributes</span>&quot; <span style="color: red">xdt:Locator</span><span style="color: blue">=</span>&quot;<span style="color: blue">Match(name)</span>&quot;<span style="color: blue">/&gt;
    &lt;/</span><span style="color: #a31515">sc:ConfigurationSettings</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">sc:Role</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">sc:ServiceConfiguration</span><span style="color: blue">&gt;
</span></pre>
<p>In this file we change the number of instances required for our web application to 2 and replace the diagnostics connection string with a string pointing to a Windows Azure storage account. </p>
<p>Notice that we explicitly qualify the service configuration namespace in this transform file. This is necessary in order for the current version of the <em>TransformXml</em> task to correctly recognize and match elements in the transform file to the elements in the original XML file. </p>
<h4>Conclusion</h4>
<p>Config file transformation offers an effective solution for managing environment-specific configuration settings for internal applications. Compared to other approaches, such as maintaining environment-specific configuration files and section files, config transformation has the advantage of a single file per environment with minimum duplication of common settings. Although this approach comes at the cost of having to use a new XML-based language to define transformations, its integration into the Visual Studio build process and simplicity of ongoing use make it very attractive for internal application development. Although it is only available in Visual Studio 2010 for Web application projects, other project types can be easily customized to take advantage of this functionality. </p>
<p>Just like its alternatives discussed in this article, config file transformation requires environment-specific configuration information to be stored in source control, with the rest of the application source code. Any sensitive information, such as user names and passwords embedded in connection strings or other settings, will be visible to all developers who have access to the source control repository. In order to avoid putting production systems at risk, your first choice should be to use authentication mechanisms, such as Integrated Windows Authentication, that don’t rely on storing secrets such as passwords in the configuration settings. If this is not an option, the next choice is to encrypt the configuration settings as described <a href="http://msdn.microsoft.com/en-us/library/53tyfkaw.aspx" target="_blank">here</a>. Editing the configuration files manually on each deployment can also be done as a last resort when the organization’s IT policy prevents developers from accessing production environment and from storing production configuration in source control. In such cases config transformation can still be used for continuous deployment to development and test environments the team has access to.</p>
<p>Because config file transformation occurs at build time, as opposed to installation or run-time, it cannot be used for shrink-wrapped software products that will be installed and configured by end-users. For such applications, having a robust and well documented installation and configuration program is still the best option. </p>
<h5>Download</h5>
<ul>
<li><a href="http://www.olegsych.com/wp-content/uploads/2010/12/config-transform-demo2.zip">Source Code</a> </li>
</ul>
<p>&copy;2012 <a href="http://www.olegsych.com">Oleg Sych</a>. All Rights Reserved.</p>.<img src="http://feeds.feedburner.com/~r/olegsych/~4/YqABqTaElYM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.olegsych.com/2010/12/config-file-transformation/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Understanding ASP.NET Dynamic Data: Entity Templates</title>
		<link>http://www.olegsych.com/2010/09/understanding-aspnet-dynamic-data-entity-templates/</link>
		<comments>http://www.olegsych.com/2010/09/understanding-aspnet-dynamic-data-entity-templates/#comments</comments>
		<pubDate>Mon, 20 Sep 2010 22:28:14 +0000</pubDate>
		<dc:creator>Oleg Sych</dc:creator>
		
		<category><![CDATA[Articles]]></category>

		<category><![CDATA[Architecture]]></category>

		<category><![CDATA[ASP.NET]]></category>

		<category><![CDATA[Dynamic Data]]></category>

		<guid isPermaLink="false">http://www.olegsych.com/2010/09/understanding-aspnet-dynamic-data-entity-templates/</guid>
		<description><![CDATA[This article explains how ASP.NET 4.0 Dynamic Data scaffolds entity templates, walks you through the process of creating a custom entity template and shows how the default entity templates supplied by Dynamic Data can be modified to reduce code duplication.]]></description>
			<content:encoded><![CDATA[<p>The only option to create a custom form layout in version 3.5 of the ASP.NET Dynamic Data was to create an entire custom page, as shown in <a href="http://www.asp.net/aspnet-in-net-35-sp1/videos/how-to-create-table-specific-custom-forms-in-an-aspnet-dynamic-data-application" target="_blank">this video</a> and explained in <a href="http://msdn.microsoft.com/en-us/library/cc488537.aspx" target="_blank">this article</a>. Although powerful, this approach requires you to duplicate an entire page, with all of its supporting code. Version 4.0 of ASP.NET Dynamic Data allows you to define <em>entity templates </em>which contain only the layout of a form. This article explains how Dynamic Data scaffolds entity templates, walks you through the process of creating a simple entity template and shows how default entity templates supplied by Dynamic Data can be modified to reduce the amount of code duplication.</p>
<h4>Overview of Entity Templates</h4>
<p>In version 4.0 of <a href="http://www.asp.net/dynamicdata" target="_blank">ASP.NET Dynamic Data</a>, entity templates are responsible for displaying data from a single entity (i.e. data row) in a <a href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.formview.aspx" target="_blank">FormView</a>. The screenshots below show the Insert, Edit and Details pages with parts generated by the the entity templates outlined in red.</p>
<p><a href="http://www.olegsych.com/wp-content/uploads/2010/09/inserttemplate.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Entity Insert Page" border="0" alt="Entity Insert Page" src="http://www.olegsych.com/wp-content/uploads/2010/09/inserttemplate-thumb.png" width="208" height="290" /></a>&#160;<a href="http://www.olegsych.com/wp-content/uploads/2010/09/edittemplate.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Entity Edit Page" border="0" alt="Entity Edit Page" src="http://www.olegsych.com/wp-content/uploads/2010/09/edittemplate-thumb.png" width="221" height="290" /></a>&#160;<a href="http://www.olegsych.com/wp-content/uploads/2010/09/detailstemplate.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Entity Details Page" border="0" alt="Entity Details Page" src="http://www.olegsych.com/wp-content/uploads/2010/09/detailstemplate-thumb.png" width="128" height="290" /></a></p>
<p>Here is how the default Details.aspx page template uses the read-only Details entity template.</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">FormView </span><span style="color: red">runat</span><span style="color: blue">=&quot;server&quot; </span><span style="color: red">ID</span><span style="color: blue">=&quot;FormView1&quot;
  </span><span style="color: red">DataSourceID</span><span style="color: blue">=&quot;DetailsDataSource&quot;</span><span style="color: blue">&gt;
  &lt;</span><span style="color: maroon">ItemTemplate</span><span style="color: blue">&gt;
    &lt;</span><span style="color: maroon">table</span><span style="color: blue">&gt;
      &lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">DynamicEntity </span><span style="color: red">runat</span><span style="color: blue">=&quot;server&quot; /&gt;
      &lt;</span><span style="color: maroon">tr</span><span style="color: blue">&gt;
        &lt;</span><span style="color: maroon">td</span><span style="color: blue">&gt;
          &lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">DynamicHyperLink </span><span style="color: red">runat</span><span style="color: blue">=&quot;server&quot;
            </span><span style="color: red">Action</span><span style="color: blue">=&quot;Edit&quot; </span><span style="color: red">Text</span><span style="color: blue">=&quot;Edit&quot; /&gt;
          &lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">LinkButton </span><span style="color: red">runat</span><span style="color: blue">=&quot;server&quot;
            </span><span style="color: red">CommandName</span><span style="color: blue">=&quot;Delete&quot; </span><span style="color: red">Text</span><span style="color: blue">=&quot;Delete&quot;</span><span style="color: blue">/&gt;
        &lt;/</span><span style="color: maroon">td</span><span style="color: blue">&gt;
      &lt;/</span><span style="color: maroon">tr</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: maroon">table</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: maroon">ItemTemplate</span><span style="color: blue">&gt;
</span><span style="color: blue">&lt;/</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">FormView</span><span style="color: blue">&gt;</span></pre>
<p>Notice the <a href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.dynamicentity.aspx" target="_blank">DynamicEntity</a> control in the middle of the <a href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.formview.aspx" target="_blank">FormView</a> above. During the <a href="http://msdn.microsoft.com/en-us/library/ms178472.aspx" target="_blank">load</a> stage of the ASP.NET page lifecycle, <em>DynamicEntity</em> control finds the appropriate user control in the <em>EntityTemplates</em> folder of the Dynamic Data application and dynamically creates it to provide entity-specific portion of the page.</p>
<p>Here is how the default entity template (<em>EntityTemplates\Default.ascx</em>) user control is implemented.</p>
<pre class="code"><span style="background: yellow">&lt;%</span><span style="color: blue">@ </span><span style="color: maroon">Control </span><span style="color: red">Language</span><span style="color: blue">=&quot;C#&quot; </span><span style="color: red">CodeBehind</span><span style="color: blue">=&quot;Default.ascx.cs&quot;
  </span><span style="color: red">Inherits</span><span style="color: blue">=&quot;DynamicDataDemo.DefaultEntityTemplate&quot; </span><span style="background: yellow">%&gt;
</span><span style="color: blue">&lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">EntityTemplate </span><span style="color: red">runat</span><span style="color: blue">=&quot;server&quot; </span><span style="color: red">ID</span><span style="color: blue">=&quot;EntityTemplate1&quot;&gt;
  &lt;</span><span style="color: maroon">ItemTemplate</span><span style="color: blue">&gt;
    &lt;</span><span style="color: maroon">tr</span><span style="color: blue">&gt;
      &lt;</span><span style="color: maroon">td</span><span style="color: blue">&gt;
        &lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">Label </span><span style="color: red">runat</span><span style="color: blue">=&quot;server&quot; </span><span style="color: red">OnInit</span><span style="color: blue">=&quot;Label_Init&quot; /&gt;
      &lt;/</span><span style="color: maroon">td</span><span style="color: blue">&gt;
      &lt;</span><span style="color: maroon">td</span><span style="color: blue">&gt;
        &lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">DynamicControl </span><span style="color: red">runat</span><span style="color: blue">=&quot;server&quot;
          </span><span style="color: red">OnInit</span><span style="color: blue">=&quot;DynamicControl_Init&quot; /&gt;
      &lt;/</span><span style="color: maroon">td</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: maroon">tr</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: maroon">ItemTemplate</span><span style="color: blue">&gt;
&lt;/</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">EntityTemplate</span><span style="color: blue">&gt;</span></pre>
<p>This user control inherits from the <a href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.entitytemplateusercontrol.aspx" target="_blank">EntityTemplateUserControl</a> class provided by Dynamic Data. This base class provides access to several properties worth mentioning, such as <a href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.entitytemplateusercontrol.table.aspx" target="_blank">Table</a>, which gives you the <a href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.metatable.aspx" target="_blank">MetaTable</a> describing the current entity,<em> and </em><a href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.entitytemplateusercontrol.mode.aspx" target="_blank">Mode</a>, which determines whether the entity should be displayed in edit, insert or read-only mode. The <a href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.entitytemplate.aspx" target="_blank">EntityTemplate</a> control, provided by Dynamic Data, is essentially a <a href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.repeater.aspx" target="_blank">repeater</a> that our entity template user control uses to generate HTML for each property of the current entity. <a href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.dynamiccontrol.aspx" target="_blank">DynamicControl</a>, also provided by Dynamic Data, dynamically loads a <em>field template</em> appropriate for the current property, based on its type and attributes. All that is needed is a little bit of code (shown below) to wire up the controls.</p>
<pre class="code"><span style="color: blue">using </span>System;
<span style="color: blue">using </span>System.Collections.Generic;
<span style="color: blue">using </span>System.Web.DynamicData;
<span style="color: blue">using </span>System.Web.UI;
<span style="color: blue">using </span>System.Web.UI.WebControls;

<span style="color: blue">namespace </span>DynamicDataDemo
{
    <span style="color: blue">public partial class </span><span style="color: #2b91af">DefaultEntityTemplate
        </span>: <span style="color: #2b91af">EntityTemplateUserControl
    </span>{
        <span style="color: blue">private </span><span style="color: #2b91af">MetaColumn </span>currentColumn;

        <span style="color: blue">protected override void </span>OnLoad(<span style="color: #2b91af">EventArgs </span>e)
        {
            <span style="color: #2b91af">IEnumerable</span>&lt;<span style="color: #2b91af">MetaColumn</span>&gt; columns =
                <span style="color: blue">this</span>.Table.GetScaffoldColumns(
                    <span style="color: blue">this</span>.Mode, <span style="color: blue">this</span>.ContainerType);

            <span style="color: blue">foreach </span>(<span style="color: #2b91af">MetaColumn </span>column <span style="color: blue">in </span>columns)
            {
                <span style="color: blue">this</span>.currentColumn = column;

                <span style="color: #2b91af">Control </span>item = <span style="color: blue">new </span><span style="color: #2b91af">_NamingContainer</span>();
                <span style="color: blue">this</span>.entityTemplate.ItemTemplate.InstantiateIn(item);
                <span style="color: blue">this</span>.entityTemplate.Controls.Add(item);
            }
        }

        <span style="color: blue">protected void </span>DynamicControl_Init(<span style="color: blue">object </span>sender, <span style="color: #2b91af">EventArgs </span>e)
        {
            <span style="color: #2b91af">DynamicControl </span>dynamicControl = (<span style="color: #2b91af">DynamicControl</span>)sender;
            dynamicControl.DataField = <span style="color: blue">this</span>.currentColumn.Name;
        }

        <span style="color: blue">protected void </span>Label_Init(<span style="color: blue">object </span>sender, <span style="color: #2b91af">EventArgs </span>e)
        {
            <span style="color: #2b91af">Label </span>label = (<span style="color: #2b91af">Label</span>)sender;
            label.Text = <span style="color: blue">this</span>.currentColumn.DisplayName;
        }

        <span style="color: blue">public class </span><span style="color: #2b91af">_NamingContainer </span>: <span style="color: #2b91af">Control</span>, <span style="color: #2b91af">INamingContainer </span>{ }
    }
}</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>Most of the magic happens in the <a href="http://msdn.microsoft.com/en-us/library/system.web.ui.control.onload.aspx" target="_blank">OnLoad</a> method of the user control. To determine which controls to display, it calls the <a href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.metatable.getscaffoldcolumns.aspx" target="_blank">GetScaffoldColumns</a> method of the <em>MetaTable</em> class. This method returns a list of <a href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.metacolumn.aspx" target="_blank">MetaColumn</a> objects, each describing a single property of our entity, including property’s <a href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.metacolumn.name.aspx" target="_blank">Name</a> and <a href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.metacolumn.displayname.aspx" target="_blank">DisplayName</a>. Having obtained the list of <em>MetaColumns</em>, the <em>OnLoad</em> method instantiates the <em>EntityTemplate</em> for each column to generate the controls. Essentially, this code implements a form of the <a href="http://msdn.microsoft.com/en-us/library/36574bf6.aspx" target="_blank">templated user control</a>, a well established ASP.NET pattern. </p>
<p>The rest of the magic is done by the <em>DynamicControl</em> instances generated for each column. As you can see in the <em>DynamicControl_Init</em> method, we initialize its <a href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.dynamiccontrol.datafield.aspx" target="_blank">DataField</a> property with the name of the current <em>MetaColumn</em>. During the load stage, <em>DynamicControl</em> will automatically find an appropriate field template and include it in the page as described <a href="http://msdn.microsoft.com/en-us/library/ee377606.aspx#field_templates" target="_blank">here</a>.</p>
<h4><a href="http://www.olegsych.com/wp-content/uploads/2010/09/image.png"><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="image" border="0" alt="image" align="right" src="http://www.olegsych.com/wp-content/uploads/2010/09/image-thumb.png" width="202" height="290" /></a>Entity Template Scaffolding</h4>
<p>Out of the box, Dynamic Data provides three entity templates called <em>Default</em>, <em>Default_Insert</em> and <em>Default_Edit</em>. The <em>Default</em> entity template is used by the <em>Details</em> page and the <em>Default_Insert</em> and <em>Default_Edit</em> entity templates are used by the <em>Insert</em> and <em>Edit </em>pages respectively.</p>
<p>The entity template user controls follow a specific naming convention:</p>
<p><strong>{Name}.ascx<br />
    <br /></strong><strong>{Name}_{Mode}.ascx</strong></p>
<ul>
<li><em>Name </em>is the name of a <a href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.metatable.aspx" target="_blank">MetaTable</a> or the <a href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.dynamicentity.uihint.aspx" target="_blank">UIHint</a> that can be specified explicitly on the <em>DynamicEntity</em> control. Typically, this will be the name of a MetaTable, which will match the name of the property generated in your context class you would normally use to access the data, such as <em>Products</em> or <em>Customers</em>. However, if you use inheritance in your data model, table name will match the class name for derived entity types and will typically have singular form, such as <em>Customer.</em></li>
<li><em>Mode</em> can be either <a href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.databoundcontrolmode.aspx" target="_blank">Edit</a> or <a href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.databoundcontrolmode.aspx" target="_blank">Insert</a>. An entity template that doesn’t include mode in its name is assumed to be a <a href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.databoundcontrolmode.aspx" target="_blank">ReadOnly</a> template.</li>
</ul>
<p>During the load stage of control lifecycle, the <em>DynamicEntity</em> control uses <a href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.metamodel.entitytemplatefactory.aspx" target="_blank">EntityTemplateFactory</a> of the default <a href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.metamodel.aspx" target="_blank">MetaModel</a> to find and create a matching entity template user control. The factory will first try the most specific name, such as <em>Products_Insert.ascx</em>. If a file with this name does not exist, it will try changing the name and the mode portions of the file name until it locates the first suitable match. The table below shows the order used by the <em>EntityTemplateFactory</em> to find entity templates.</p>
<table border="1" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td><strong>Insert Mode</strong></td>
<td><strong>Edit Mode</strong></td>
<td><strong>Read-only Mode</strong></td>
</tr>
<tr valign="top">
<td>{UIHint}_Insert.ascx<br />
        <br />{UIHint}_Edit.ascx </p>
<p>{TableName}_Insert.ascx </p>
<p>{TableName}_Edit.ascx </p>
<p>Default_Insert.ascx </p>
<p>Default_Edit.ascx </p>
<p>{UIHint}.ascx </p>
<p>{TableName}.ascx </p>
<p>Default.ascx </td>
<td>{UIHint}_Edit.ascx<br />
        <br />{TableName}_Edit.ascx </p>
<p>Default_Edit.ascx </p>
<p>{UIHint}.ascx </p>
<p>{TableName}.ascx </p>
<p>Default.ascx </td>
<td>{UIHint}.ascx<br />
        <br />{TableName}.ascx </p>
<p>Default.ascx </td>
</tr>
</tbody>
</table>
<p>&#160;</p>
<h4><a href="http://www.olegsych.com/wp-content/uploads/2010/09/image1.png"><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="Custom Product Entity Template" border="0" alt="Custom Product Entity Template" align="right" src="http://www.olegsych.com/wp-content/uploads/2010/09/image-thumb1.png" width="240" height="220" /></a> Creating a Custom Entity Template</h4>
<p>If you are not satisfied with the single-column layout that default entity templates produce, you can create a custom entity template by creating a special user control with the name that matches your the name of your entity and the mode of your page and placing it in the <em>EntityTemplates </em>folder of your Dynamic Data web project. The screenshot on the right shows output produced by the <em>Details.aspx </em>page using a custom <em>Products.ascx </em>entity template. Again, output of the entity template is outlined in red.</p>
<p>Here is the implementation of the <em>EntityTemplates\Products.ascx</em> (without the formatting attributes, which were removed for clarity). </p>
</p>
<pre class="code"><span style="background: yellow">&lt;%</span><span style="color: blue">@ </span><span style="color: maroon">Control </span><span style="color: red">Language</span><span style="color: blue">=&quot;C#&quot; </span><span style="color: red">AutoEventWireup</span><span style="color: blue">=&quot;true&quot; </span><span style="color: red">CodeBehind</span><span style="color: blue">=&quot;Products.ascx.cs&quot;
</span><span style="color: red">Inherits</span><span style="color: blue">=&quot;DynamicDataDemo.DynamicData.EntityTemplates.ProductsEntityTemplate&quot; </span><span style="background: yellow">%&gt;

</span><span style="color: blue">&lt;</span><span style="color: maroon">tr</span><span style="color: blue">&gt;
  &lt;</span><span style="color: maroon">td</span><span style="color: blue">&gt;
    &lt;</span><span style="color: maroon">table</span><span style="color: blue">&gt;
      &lt;</span><span style="color: maroon">tr</span><span style="color: blue">&gt;
        &lt;</span><span style="color: maroon">td</span><span style="color: blue">&gt;</span>Name<span style="color: blue">&lt;/</span><span style="color: maroon">td</span><span style="color: blue">&gt;
        &lt;</span><span style="color: maroon">td</span><span style="color: blue">&gt;
          &lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">DynamicControl </span><span style="color: red">runat</span><span style="color: blue">=&quot;server&quot; </span><span style="color: red">DataField</span><span style="color: blue">=&quot;ProductName&quot;
            </span><span style="color: red">OnInit</span><span style="color: blue">=&quot;DynamicControl_Init&quot;/&gt;
        &lt;/</span><span style="color: maroon">td</span><span style="color: blue">&gt;
      &lt;/</span><span style="color: maroon">tr</span><span style="color: blue">&gt;
      &lt;</span><span style="color: maroon">tr</span><span style="color: blue">&gt;
        &lt;</span><span style="color: maroon">td</span><span style="color: blue">&gt;</span>Category<span style="color: blue">&lt;/</span><span style="color: maroon">td</span><span style="color: blue">&gt;
        &lt;</span><span style="color: maroon">td</span><span style="color: blue">&gt;
          &lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">DynamicControl </span><span style="color: red">runat</span><span style="color: blue">=&quot;server&quot; </span><span style="color: red">DataField</span><span style="color: blue">=&quot;Category&quot;
            </span><span style="color: red">OnInit</span><span style="color: blue">=&quot;DynamicControl_Init&quot;/&gt;
        &lt;/</span><span style="color: maroon">td</span><span style="color: blue">&gt;
      &lt;/</span><span style="color: maroon">tr</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: maroon">table</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: maroon">td</span><span style="color: blue">&gt;
  &lt;</span><span style="color: maroon">td</span><span style="color: blue">&gt;
    &lt;</span><span style="color: maroon">table</span><span style="color: blue">&gt;
      &lt;</span><span style="color: maroon">tr</span><span style="color: blue">&gt;
        &lt;</span><span style="color: maroon">td</span><span style="color: blue">&gt;</span>Supplier<span style="color: blue">&lt;/</span><span style="color: maroon">td</span><span style="color: blue">&gt;
        &lt;</span><span style="color: maroon">td</span><span style="color: blue">&gt;
          &lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">DynamicControl </span><span style="color: red">runat</span><span style="color: blue">=&quot;server&quot; </span><span style="color: red">DataField</span><span style="color: blue">=&quot;Supplier&quot;
            </span><span style="color: red">OnInit</span><span style="color: blue">=&quot;DynamicControl_Init&quot;/&gt;
        &lt;/</span><span style="color: maroon">td</span><span style="color: blue">&gt;
      &lt;/</span><span style="color: maroon">tr</span><span style="color: blue">&gt;
      &lt;</span><span style="color: maroon">tr</span><span style="color: blue">&gt;
        &lt;</span><span style="color: maroon">td</span><span style="color: blue">&gt;</span>Units in stock<span style="color: blue">&lt;/</span><span style="color: maroon">td</span><span style="color: blue">&gt;
        &lt;</span><span style="color: maroon">td</span><span style="color: blue">&gt;
          &lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">DynamicControl </span><span style="color: red">runat</span><span style="color: blue">=&quot;server&quot; </span><span style="color: red">DataField</span><span style="color: blue">=&quot;UnitsInStock&quot;
            </span><span style="color: red">OnInit</span><span style="color: blue">=&quot;DynamicControl_Init&quot;/&gt;
        &lt;/</span><span style="color: maroon">td</span><span style="color: blue">&gt;
      &lt;/</span><span style="color: maroon">tr</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: maroon">table</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: maroon">td</span><span style="color: blue">&gt;
&lt;/</span><span style="color: maroon">tr</span><span style="color: blue">&gt;</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>Notice that we use <em>DynamicControl</em> instances to dynamically generate appropriate field templates for the properties we want to see – <em>ProductName</em>, <em>Category</em>, <em>Supplier</em> and <em>UnitsInStock</em>. For <em>ProductName</em>, DynamicControl will choose the <em>Text.ascx</em> field template, which will produce plain text output, but for the foreign key columns, <em>Category</em> and <em>Supplier</em>, it will choose the <em>ForeignKey.ascx</em> field template, which will produce hyperlinks to the dynamic <em>Details.aspx </em>pages for the <em>Category</em> and <em>Supplier </em>entities respectively.</p>
<p>Our custom entity template defines the required layout for the <em>Product</em> entity, without re-implementing any of the field presentation logic. This power becomes even more apparent in <em>Insert</em> and <em>Edit </em>pages (shown below). The editable versions of the field templates make extensive use of not only web controls, but also client- and server-side validators. Although this logic would be easy to implement by copy-and-paste initially, consistently maintaining it across different custom pages and controls quickly becomes a serious maintenance challenge. Thanks to the <em>DynamicControl</em> we can maintain this logic in a single place – the field templates and reuse it in the custom entity templates without incurring the penalty of code duplication.</p>
<p><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Edit Page with Custom Entity Template" border="0" alt="Edit Page with Custom Entity Template" src="http://www.olegsych.com/wp-content/uploads/2010/09/image15.png" width="557" height="353" /></p>
<p>In order to make the field templates work correctly in <em>Edit </em>and <em>Insert</em> mode, we need to dynamically initialize the <a href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.dynamiccontrol.mode.aspx" target="_blank">Mode</a> property for each <em>DynamicControl</em> in the template<em>.</em> This is done in the <em>DynamicControl_Init</em> method defined in the code-behind. During the initialization stage of control lifecycle, <em>DynamicControl</em> passes this value to the <a href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.metamodel.fieldtemplatefactory.aspx" target="_blank">FieldTemplateFactory</a> to locate and dynamically create the <em>editable</em> versions of the field templates. </p>
<pre class="code"><span style="color: blue">using </span>System;
<span style="color: blue">using </span>System.Web.DynamicData;

<span style="color: blue">namespace </span>DynamicDataDemo.DynamicData.EntityTemplates
{
    <span style="color: blue">public partial class </span><span style="color: #2b91af">ProductsEntityTemplate </span>: <span style="color: #2b91af">EntityTemplateUserControl
    </span>{
        <span style="color: blue">protected void </span>DynamicControl_Init(<span style="color: blue">object </span>sender, <span style="color: #2b91af">EventArgs </span>e)
        {
            <span style="color: #2b91af">DynamicControl </span>dynamicControl = (<span style="color: #2b91af">DynamicControl</span>)sender;
            dynamicControl.Mode = <span style="color: blue">this</span>.Mode;
        }
    }
}</pre>
<h4>Improving Default Entity Templates</h4>
<p>Unfortunately, our <em>Products.ascx</em> cannot be used by the Edit.aspx page template immediately. In Edit mode, without an entity template called <em>Products_Edit.ascx</em>, the <em>EntityTemplateFactory</em> will try <em>Default_Edit.ascx</em> before it tries the <em>Products.ascx</em>. In order to make a custom entity template for Edit and Insert mode, we would need to save a copy of <em>Products.ascx</em> as <em>Products_Edit.ascx</em>. This last template would be reused by both <em>Edit.aspx </em>and <em>Insert.aspx</em> because the <em>EntityTemplateFactory</em> assumes that edit-mode entity templates can be used in insert mode as well. </p>
<p>Having two identical copies of the same code is not ideal and will quickly get out of hand as the number of custom entity templates grows. Your first attempt to solve the code duplication problem might be to extract this code into a user control, such as <em>ProductsTemplate.ascx,</em> and reuse it in both <em>Products.ascx</em> and <em>Products_Edit.ascx</em>. This approach works, but you end up with even more files in your project, three user controls for each entity that needs a custom template, all in order to work around the logic the <em>EntityTemplateFactory</em> uses to resolve entity templates. There has to be a better way!</p>
<p>Taking a closer look at the <em>Default.aspx</em>, <em>Default_Edit.ascx</em> and <em>Default_Insert.ascx </em>entity templates provided by the Dynamic Data, you will notice that these user controls are very similar. We can easily combine their logic into the <em>Default.ascx</em> and delete the <em>Default_Edit.ascx</em> and <em>Default_Insert.ascx.</em> This will not only eliminate the code duplication in the <em>default </em>entity templates; it will also eliminate the need to duplicate code or create multiple files for <em>custom </em>entity templates as well. </p>
<p>Here is what the new <em>Default.ascx</em> looks like without formatting attributes.</p>
<pre class="code"><span style="background: yellow">&lt;%</span><span style="color: blue">@ </span><span style="color: maroon">Control </span><span style="color: red">Language</span><span style="color: blue">=&quot;C#&quot; </span><span style="color: red">CodeBehind</span><span style="color: blue">=&quot;Default.ascx.cs&quot;
  </span><span style="color: red">Inherits</span><span style="color: blue">=&quot;DynamicDataDemo.DefaultEntityTemplate&quot; </span><span style="background: yellow">%&gt;
</span><span style="color: blue">&lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">EntityTemplate </span><span style="color: red">runat</span><span style="color: blue">=&quot;server&quot; </span><span style="color: red">ID</span><span style="color: blue">=&quot;entityTemplate&quot;&gt;
  &lt;</span><span style="color: maroon">ItemTemplate</span><span style="color: blue">&gt;
    &lt;</span><span style="color: maroon">tr</span><span style="color: blue">&gt;
      &lt;</span><span style="color: maroon">td</span><span style="color: blue">&gt;
        &lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">Label </span><span style="color: red">runat</span><span style="color: blue">=&quot;server&quot; </span><span style="color: red">OnInit</span><span style="color: blue">=&quot;Label_Init&quot;
          </span><span style="color: red">OnPreRender</span><span style="color: blue">=&quot;Label_PreRender&quot; /&gt;
      &lt;/</span><span style="color: maroon">td</span><span style="color: blue">&gt;
      &lt;</span><span style="color: maroon">td</span><span style="color: blue">&gt;
        &lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">DynamicControl </span><span style="color: red">ID</span><span style="color: blue">=&quot;dynamicControl&quot;
          </span><span style="color: red">runat</span><span style="color: blue">=&quot;server&quot; </span><span style="color: red">OnInit</span><span style="color: blue">=&quot;DynamicControl_Init&quot; /&gt;
      &lt;/</span><span style="color: maroon">td</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: maroon">tr</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: maroon">ItemTemplate</span><span style="color: blue">&gt;
&lt;/</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">EntityTemplate</span><span style="color: blue">&gt;</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>Note the addition of the <a href="http://msdn.microsoft.com/en-us/library/system.web.ui.control.onprerender.aspx" target="_blank">OnPreRender</a> event handler for the <a href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.label.aspx" target="_blank">Label</a> control. The <em>Label_PreRender</em> method associates the label with the dynamically generated <a href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.fieldtemplateusercontrol.datacontrol.aspx" target="_blank">DataControl</a>. Another important difference is how the <a href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.dynamiccontrol.mode.aspx" target="_blank">Mode</a> property of the <em>DynamicControl</em> is initialized. In the templates supplied by Dynamic Data, this is done in the control markup. In our new template this is done dynamically, in the <em>DynamicControl_Init</em> method, which initializes it based on the <a href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.entitytemplateusercontrol.mode.aspx" target="_blank">Mode</a> of the entity template itself. </p>
<p>Here is the new code-behind file, <em>Default.ascx.cs.</em></p>
<pre class="code"><span style="color: blue">using </span>System;
<span style="color: blue">using </span>System.Collections.Generic;
<span style="color: blue">using </span>System.Web.DynamicData;
<span style="color: blue">using </span>System.Web.UI;
<span style="color: blue">using </span>System.Web.UI.WebControls;

<span style="color: blue">namespace </span>DynamicDataDemo
{
    <span style="color: blue">public partial class </span><span style="color: #2b91af">DefaultEntityTemplate
        </span>: <span style="color: #2b91af">EntityTemplateUserControl
    </span>{
        <span style="color: blue">private </span><span style="color: #2b91af">MetaColumn </span>currentColumn;

        <span style="color: blue">protected override void </span>OnLoad(<span style="color: #2b91af">EventArgs </span>e)
        {
            <span style="color: #2b91af">IEnumerable</span>&lt;<span style="color: #2b91af">MetaColumn</span>&gt; columns =
                <span style="color: blue">this</span>.Table.GetScaffoldColumns(
                    <span style="color: blue">this</span>.Mode, <span style="color: blue">this</span>.ContainerType);

            <span style="color: blue">foreach </span>(<span style="color: #2b91af">MetaColumn </span>column <span style="color: blue">in </span>columns)
            {
                <span style="color: blue">this</span>.currentColumn = column;

                <span style="color: #2b91af">Control </span>item = <span style="color: blue">new </span><span style="color: #2b91af">_NamingContainer</span>();
                <span style="color: blue">this</span>.entityTemplate.ItemTemplate.InstantiateIn(item);
                <span style="color: blue">this</span>.entityTemplate.Controls.Add(item);
            }
        }

        <span style="color: blue">protected void </span>DynamicControl_Init(<span style="color: blue">object </span>sender, <span style="color: #2b91af">EventArgs </span>e)
        {
            <span style="color: #2b91af">DynamicControl </span>dynamicControl = (<span style="color: #2b91af">DynamicControl</span>)sender;
            dynamicControl.DataField = <span style="color: blue">this</span>.currentColumn.Name;
            dynamicControl.Mode = <span style="color: blue">this</span>.Mode;
        }

        <span style="color: blue">protected void </span>Label_Init(<span style="color: blue">object </span>sender, <span style="color: #2b91af">EventArgs </span>e)
        {
            <span style="color: #2b91af">Label </span>label = (<span style="color: #2b91af">Label</span>)sender;
            label.Text = <span style="color: blue">this</span>.currentColumn.DisplayName;
        }

        <span style="color: blue">protected void </span>Label_PreRender(<span style="color: blue">object </span>sender, <span style="color: #2b91af">EventArgs </span>e)
        {
            <span style="color: #2b91af">Label </span>label = (<span style="color: #2b91af">Label</span>)sender;

            <span style="color: #2b91af">DynamicControl </span>dynamicControl =
                (<span style="color: #2b91af">DynamicControl</span>)label.FindControl(<span style="color: #a31515">&quot;dynamicControl&quot;</span>);

            <span style="color: #2b91af">FieldTemplateUserControl </span>fieldTemplate =
                dynamicControl.FieldTemplate <span style="color: blue">as </span><span style="color: #2b91af">FieldTemplateUserControl</span>;

            <span style="color: blue">if </span>(fieldTemplate != <span style="color: blue">null </span>&amp;&amp; fieldTemplate.DataControl != <span style="color: blue">null</span>)
            {
                label.AssociatedControlID =
                    fieldTemplate.DataControl.GetUniqueIDRelativeTo(label);
            }
        }

        <span style="color: blue">public class </span><span style="color: #2b91af">_NamingContainer </span>: <span style="color: #2b91af">Control</span>, <span style="color: #2b91af">INamingContainer </span>{ }
    }
}</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<h4>Closing Thoughts</h4>
<p>Entity templates are a very powerful addition to the ASP.NET Dynamic Data. A single <em>default</em> entity template user control can define the form layout for <em>all </em>entity types in your model in <em>three </em>different modes – ReadOnly (<em>Details.aspx</em>), Insert (<em>Insert.aspx</em>) and Edit (<em>Edit.aspx</em>). A <em>custom</em> entity template can be quickly created to replace the standard single-column form layout with a required custom layout, which again, can be reused in all three different modes. This power truly shines in Insert and Edit pages, where entity templates give you the ability to modify the form layout logic completely independently from the data entry and validation logic encapsulated by the field templates. While the default entity templates supplied by the Dynamic Data project are mode-specific and encourage code duplication, you can easily combine them into a single entity template and eliminate the need to create mode-specific custom entity templates as well. </p>
<h4>Download</h4>
<p><a href="http://www.olegsych.com/wp-content/uploads/2010/09/dynamicdatademo.zip" target="_blank">Source Code</a>.</p>
<p>&copy;2012 <a href="http://www.olegsych.com">Oleg Sych</a>. All Rights Reserved.</p>.<img src="http://feeds.feedburner.com/~r/olegsych/~4/SwwXLaD4BFo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.olegsych.com/2010/09/understanding-aspnet-dynamic-data-entity-templates/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Extending ASP.NET Dynamic Data: Filtering with Joins</title>
		<link>http://www.olegsych.com/2010/08/extending-aspnet-dynamic-data-filtering-with-joins/</link>
		<comments>http://www.olegsych.com/2010/08/extending-aspnet-dynamic-data-filtering-with-joins/#comments</comments>
		<pubDate>Mon, 23 Aug 2010 19:10:34 +0000</pubDate>
		<dc:creator>Oleg Sych</dc:creator>
		
		<category><![CDATA[Articles]]></category>

		<category><![CDATA[ASP.NET]]></category>

		<category><![CDATA[Dynamic Data]]></category>

		<guid isPermaLink="false">http://www.olegsych.com/2010/08/extending-aspnet-dynamic-data-filtering-with-joins/</guid>
		<description><![CDATA[ASP.NET Dynamic Data provides built-in capabilities for generating search screens based on columns of a single entity. Real-world applications are often required to provide more sophisticated search capabilities based on multiple related tables, such as searching for orders placed by customers in a particular state. This article discusses current architectural limitations of the framework and demonstrates how to implement join-based search capabilities in Dynamic Data applications.]]></description>
			<content:encoded><![CDATA[<p>Out of the box, <a href="http://www.asp.net/dynamicdata" target="_blank">ASP.NET Dynamic Data</a> automatically generates search screens for entities based on their own columns. Here is an example of a search screen it generated for the Order table of the Northwind model from the <a href="http://www.olegsych.com/2010/07/understanding-aspnet-dynamic-data-filter-templates/" target="_blank">previous article</a>. </p>
<p><a href="http://www.olegsych.com/wp-content/uploads/2010/08/image.png"><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="image" border="0" alt="image" align="left" src="http://www.olegsych.com/wp-content/uploads/2010/08/image-thumb.png" width="260" height="173" /></a> </p>
<p>This screen contains controls for all columns of the <em>Order</em> table for which Dynamic Data can generate filter controls. This includes controls for boolean, enumeration and foreign key columns the framework provides out of the box, as well as the custom filter control for <a href="http://msdn.microsoft.com/en-us/library/system.datetime.aspx" target="_blank">DateTime</a> columns we have added to the application. Although in this example we still don’t have filter controls for other common data types, such as string and numeric columns, implementing them is very straightforward and similar to the implementation of our <em>DateTimeFilter</em>. The real limitation here is that we cannot search the <em>Order</em> table using filters based on related tables. For example, what if we need to give the users of our application the ability to search for orders placed by customers in a particular state or zip code? The short answer is that Dynamic Data doesn’t support filtering based on data in related tables. However, it is possible to make it cooperate. Here is the long answer…</p>
<h4>The Approach</h4>
<p>As usual with Dynamic Data, it is helpful to first work through a particular scenario using the traditional, static code. If we were to build a search screen for the <em>Orders </em>table using regular ASP.NET controls and the ADO.NET Entity Framework, we would create a page with text boxes, drop-down lists and other controls for users to enter search criteria and use LINQ to Entities to filter the query results, like so.</p>
<pre class="code"><span style="color: blue">using </span>(<span style="color: #2b91af">NorthwindEntities </span>context = <span style="color: blue">new </span><span style="color: #2b91af">NorthwindEntities</span>())
{
    <span style="color: blue">var </span>query = <span style="color: blue">from </span>o <span style="color: blue">in </span>context.Orders
                <span style="color: blue">where </span>o.Customer.PostalCode == <span style="color: #a31515">&quot;33609&quot;
                </span><span style="color: blue">select </span>o;
    <span style="color: #2b91af">Order</span>[] results = query.ToArray();
}</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>Of course, this would not work very well if our page allowed a <em>number</em> of different criteria to be specified for the <em>Customer</em> (parent) table as well as for the <em>Order</em> (child) table. Let’s say that we have a dozen different filter controls on our search page for the user to choose from, but they only need to find orders placed by Customers with zip code 33609 and shipped to Ukraine. We would probably change the code to look more like this.</p>
<p><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a></p>
<pre class="code"><span style="color: blue">using </span>(<span style="color: #2b91af">NorthwindEntities </span>context = <span style="color: blue">new </span><span style="color: #2b91af">NorthwindEntities</span>())
{
    <span style="color: #2b91af">IQueryable</span>&lt;<span style="color: #2b91af">Customer</span>&gt; parentQuery = context.Customers;
    <span style="color: blue">if </span>(custZip.Text != <span style="color: blue">string</span>.Empty)
        parentQuery = parentQuery.Where(c =&gt; c.PostalCode == custZip.Text);
    <span style="color: blue">if </span>(custCountry.Text != <span style="color: blue">string</span>.Empty)
        parentQuery = parentQuery.Where(c =&gt; c.Country == custCountry.Text);

    <span style="color: #2b91af">IQueryable</span>&lt;<span style="color: #2b91af">Order</span>&gt; childQuery = context.Orders;
    <span style="color: blue">if </span>(shipZip.Text != <span style="color: blue">string</span>.Empty)
        childQuery = childQuery.Where(o =&gt; o.ShipPostalCode == shipZip.Text);
    <span style="color: blue">if </span>(shipCountry.Text != <span style="color: blue">string</span>.Empty)
        childQuery = childQuery.Where(o =&gt; o.ShipCountry == shipCountry.Text);

    <span style="color: blue">var </span>query = <span style="color: blue">from </span>customer <span style="color: blue">in </span>parentQuery
                <span style="color: blue">join </span>order <span style="color: blue">in </span>childQuery
                <span style="color: blue">on </span>customer.CustomerID <span style="color: blue">equals </span>order.CustomerID
                <span style="color: blue">select </span>order;

    <span style="color: #2b91af">Order</span>[] results = query.ToArray();
}</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>This way we can check each of our filter controls and generate Where calls for the parent, <em>Customers </em>table, and for the child, Orders table, and then join the two queries to get the list of orders that meet the combined criteria. This approach takes advantage of the Where call chaining that ADO.NET Entity Framework and LINQ to SQL convert into individual conditions in the Where clause of SQL Select statement. Here is what the SQL query generated by this code would look like.</p>
<pre class="code"><span style="color: blue">select </span><span style="color: teal">Customers</span><span style="color: gray">.*
</span><span style="color: blue">from </span><span style="color: teal">Customers
</span><span style="color: gray">inner join </span><span style="color: teal">Orders
</span><span style="color: blue">on </span><span style="color: teal">Orders</span><span style="color: gray">.</span><span style="color: teal">CustomerID </span><span style="color: gray">= </span><span style="color: teal">Customers</span><span style="color: gray">.</span><span style="color: teal">CustomerID
</span><span style="color: blue">where </span><span style="color: teal">Customers</span><span style="color: gray">.</span><span style="color: teal">PostalCode </span><span style="color: gray">= </span><span style="color: red">&#8216;33609&#8242;
</span><span style="color: red">  </span><span style="color: gray">and </span><span style="color: teal">Orders</span><span style="color: gray">.</span><span style="color: teal">ShipCountry </span><span style="color: gray">= </span><span style="color: red">&#8216;Ukraine&#8217;</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>Essentially, this is the same way the <a href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.queryablefilterrepeater.aspx" target="_blank">QueryableFilterRepeater</a> control works in the <em>List.aspx</em> page template. It generates <a href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.dynamicfilter.aspx" target="_blank">DynamicFilter</a>s for all columns that can be filtered in a table and calls their <em>GetQueryable</em> method allowing them to modify the search query based on the values entered in their filter controls.</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">QueryableFilterRepeater </span><span style="color: red">runat</span><span style="color: blue">=&quot;server&quot; </span><span style="color: red">ID</span><span style="color: blue">=&quot;FilterRepeater&quot;&gt;
  &lt;</span><span style="color: maroon">ItemTemplate</span><span style="color: blue">&gt;
    &lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">Label </span><span style="color: red">runat</span><span style="color: blue">=&quot;server&quot; </span><span style="color: red">Text</span><span style="color: blue">=&#8217;</span><span style="background: yellow">&lt;%</span><span style="color: blue"># </span>Eval(&quot;DisplayName&quot;) <span style="background: yellow">%&gt;</span><span style="color: blue">&#8216;
      </span><span style="color: red">OnPreRender</span><span style="color: blue">=&quot;Label_PreRender&quot; /&gt;
    &lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">DynamicFilter </span><span style="color: red">runat</span><span style="color: blue">=&quot;server&quot; </span><span style="color: red">ID</span><span style="color: blue">=&quot;DynamicFilter&quot;
      </span><span style="color: red">OnFilterChanged</span><span style="color: blue">=&quot;DynamicFilter_FilterChanged&quot; /&gt;
    &lt;</span><span style="color: maroon">br </span><span style="color: blue">/&gt;
  &lt;/</span><span style="color: maroon">ItemTemplate</span><span style="color: blue">&gt;
&lt;/</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">QueryableFilterRepeater</span><span style="color: blue">&gt;</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>What if we simply take this markup and its supporting code, put it in a new filter control, similar to the <em>DateTime.aspx</em> we created previously and implement its <a href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.queryablefilterusercontrol.getqueryable.aspx" target="_blank">GetQueryable</a> method&#160; to do the join? Unfortunately, this straightforward approach doesn’t work in the 4.0 version of ASP.NET Dynamic Data.</p>
<h4>The Problem</h4>
<p>The reason this approach doesn’t work in the current version of ASP.NET Dynamic Data lies in the implementation of the <a href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.queryablefilterrepeater.aspx" target="_blank">QueryableFilterRepeater</a> and <a href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.dynamicfilter.aspx" target="_blank">DynamicFilter</a> classes. The first stumbling block you would hit trying to make this work is how do you tell the <em>QueryableFilterRepeater </em>control that you want it to generate controls for a parent (Customer) table instead of the main (Order) table for which the page is generated? There are no public properties or methods that you could use to specify this information directly on these classes. The only way the framework provides is the <a href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.dynamicdatamanager.aspx" target="_blank">DynamicDataManager</a>, which requires you to create a data-bound control, such as a <a href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.gridview.aspx" target="_blank">GridView</a> or a <a href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.formview.aspx" target="_blank">FormView</a>; associate it with the data manager; create a data source control, such as an <a href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.entitydatasource.aspx" target="_blank">EntityDataSource</a> or a <a href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.linqdatasource.aspx" target="_blank">LinqDataSource</a>; associate it with the data-bound control; create a <a href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.queryextender.aspx" target="_blank">QueryExtender</a> control; associate it with the data source control; finally add a <a href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.dynamicfilterexpression.aspx" target="_blank">DynamicFilterExpression</a> and associate it with the QueryableFilterRepeater. </p>
<p>Even if you get all this right, this is still not going to work in a filter control. The current implementation of the <em>DynamicDataManager</em>, <em>QueryableFilterRepeater </em>and <em>DynamicFilter </em>classes perform all of their dynamic control generation logic in <a href="http://msdn.microsoft.com/en-us/library/system.web.ui.page.initcomplete.aspx" target="_blank">Page.InitComplete</a> event handlers. Unlike the <a href="http://msdn.microsoft.com/en-us/library/system.web.ui.control.init.aspx" target="_blank">Control.Init</a> and <a href="http://msdn.microsoft.com/en-us/library/system.web.ui.control.load.aspx" target="_blank">Control.Load</a> events, the page events are not automatically replayed for controls generated dynamically. When our custom filter control is initialized, the <em>Page.InitComplete </em>event has already fired, so no matter what we do, our <em>DynamicDataManager</em>, <em>QueryableFilterRepeater </em>and <em>DynamicFilter </em>simply will not initialize and will not work.</p>
<p>Why the ASP.NET team chose to use the <em>Page.InitComplete </em>event as opposed to <em>Control.Init </em>or <em>Control.Load</em> to implement filtering capabilities in Dynamic Data is beyond my understanding. If you do, please share your knowledge by posting a comment on this page; otherwise, consider voting on <a href="https://connect.microsoft.com/VisualStudio/feedback/details/588383/dont-use-page-initcomplete-in-queryablefilterrepeater-and-dynamicfilter-controls" target="_blank">Microsoft connect</a> to have this problem fixed.</p>
<h4>The Workaround</h4>
<p>Instead of relying on the built-in <em>QueryableFilterRepeater</em> and <em>DynamicFilter</em> controls, we can use the non-dynamic <a href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.repeater.aspx" target="_blank">Repeater</a> and <a href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.placeholder.aspx" target="_blank">PlaceHolder</a> controls and directly access <a href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.metamodel.filterfactory.aspx" target="_blank">MetaModel.FilterFactory</a> to dynamically create the appropriate <a href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.queryablefilterusercontrol.aspx" target="_blank">QueryableFilterUserControl</a> instances. Here is how the markup for our custom filter control could look.</p>
<pre class="code"><span style="background: yellow">&lt;%</span><span style="color: blue">@ </span><span style="color: maroon">Control </span><span style="color: red">Language</span><span style="color: blue">=&quot;C#&quot; </span><span style="color: red">AutoEventWireup</span><span style="color: blue">=&quot;true&quot; </span><span style="color: red">CodeBehind</span><span style="color: blue">=&quot;ParentTable.ascx.cs&quot;
  </span><span style="color: red">Inherits</span><span style="color: blue">=&quot;DynamicDataDemo.ParentTableFilter&quot; </span><span style="background: yellow">%&gt;
</span><span style="color: blue">&lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">Repeater </span><span style="color: red">ID</span><span style="color: blue">=&quot;repeater&quot; </span><span style="color: red">runat</span><span style="color: blue">=&quot;server&quot;&gt;
  &lt;</span><span style="color: maroon">ItemTemplate</span><span style="color: blue">&gt;
    &lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">Label </span><span style="color: red">ID</span><span style="color: blue">=&quot;label&quot; </span><span style="color: red">runat</span><span style="color: blue">=&quot;server&quot; </span><span style="color: red">Text</span><span style="color: blue">=&#8217;</span><span style="background: yellow">&lt;%</span><span style="color: blue"># </span>Eval(&quot;DisplayName&quot;) <span style="background: yellow">%&gt;</span><span style="color: blue">&#8216;/&gt;
    &lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">PlaceHolder </span><span style="color: red">ID</span><span style="color: blue">=&quot;placeHolder&quot; </span><span style="color: red">runat</span><span style="color: blue">=&quot;server&quot;
      </span><span style="color: red">OnDataBinding</span><span style="color: blue">=&quot;PlaceHolder_DataBinding&quot;/&gt;
    &lt;</span><span style="color: maroon">br </span><span style="color: blue">/&gt;
  &lt;/</span><span style="color: maroon">ItemTemplate</span><span style="color: blue">&gt;
&lt;/</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">Repeater</span><span style="color: blue">&gt;
&lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">EntityDataSource </span><span style="color: red">ID</span><span style="color: blue">=&quot;parentDataSource&quot; </span><span style="color: red">runat</span><span style="color: blue">=&quot;server&quot; /&gt;</span></pre>
<p>Notice that we have an <em>EntityDataSource</em> control for the parent table. This control will not be used to query the database, only to access the metadata. </p>
<p>In the code-behind, we get the <a href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.metatable.aspx" target="_blank">MetaTable</a> instance that describes our parent table (i.e. Customer), initialize the parent data source control and bind the repeater to the list of parent columns that can be filtered.&#160; </p>
<pre class="code"><span style="color: blue">protected override void </span>OnInit(<span style="color: #2b91af">EventArgs </span>e)
{
    <span style="color: blue">base</span>.OnInit(e);

    <span style="color: blue">var </span>foreignKeyColumn = (<span style="color: #2b91af">MetaForeignKeyColumn</span>)<span style="color: blue">this</span>.Column;
    <span style="color: #2b91af">MetaTable </span>parentTable = foreignKeyColumn.ParentTable;

    parentDataSource.ContextType = parentTable.DataContextType;
    parentDataSource.EntitySetName = parentTable.DataContextPropertyName;

    <span style="color: blue">this</span>.repeater.DataSource = parentTable.GetFilteredColumns();
    <span style="color: blue">this</span>.repeater.DataBind();

    <span style="color: blue">this</span>.EntityDataSource.ContextCreated += <span style="color: blue">this</span>.EntityDataSource_ContextCreated;
}</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>The actual code that creates appropriate filter controls is located in the <a href="http://msdn.microsoft.com/en-us/library/system.web.ui.control.databinding.aspx" target="_blank">DataBinding</a> event handler of the <em>PlaceHolder</em> control. This is where we use the Dynamic Data <a href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.filterfactory.aspx" target="_blank">FilterFactory</a> to create and initialize a new <em>QueryableFilterUserControl</em> and add it to the place holder.</p>
<p><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a></p>
<pre class="code"><span style="color: blue">protected void </span>PlaceHolder_DataBinding(<span style="color: blue">object </span>sender, <span style="color: #2b91af">EventArgs </span>e)
{
    <span style="color: #2b91af">FilterFactory </span>filterFactory = <span style="color: blue">this</span>.Column.Model.FilterFactory;
    <span style="color: #2b91af">MetaColumn </span>filterColumn = (<span style="color: #2b91af">MetaColumn</span>)<span style="color: blue">this</span>.Page.GetDataItem();

    <span style="color: blue">var </span>control = (<span style="color: #2b91af">ExtendedFilterUserControl</span>)filterFactory
        .CreateFilterControl(filterColumn, <span style="color: blue">string</span>.Empty);
    control.Initialize(filterColumn, <span style="color: blue">this</span>.parentDataSource, <span style="color: blue">null</span>);
    control.FilterChanged += <span style="color: blue">delegate </span>{ <span style="color: blue">this</span>.OnFilterChanged(); };
    <span style="color: blue">this</span>.filterControls.Add(control);

    <span style="color: #2b91af">PlaceHolder </span>placeHolder = (<span style="color: #2b91af">PlaceHolder</span>)sender;
    placeHolder.Controls.Add(control);

    <span style="color: #2b91af">Label </span>label = (<span style="color: #2b91af">Label</span>)placeHolder.FindControl(<span style="color: #a31515">&quot;label&quot;</span>);
    label.Text = filterColumn.DisplayName;
    <span style="color: blue">if </span>(control.FilterControl != <span style="color: blue">null</span>)
    {
        label.AssociatedControlID = control.FilterControl
            .GetUniqueIDRelativeTo(label);
    }
}</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>If you are reading this code carefully, you will notice that we are actually using a custom class called <em>ExtendedFilterUserControl</em>. That is because <em>QueryableFilterUserControl</em> class does not provide any public means to associate it with a particular column and a data source. To work around this limitation, we need to subclass the QueryableFilterUserControl and make its internal <em>Initialize </em>method publically available. We also need to expose its internal <em>QueryableDataSource</em> property in order to generate LINQ join queries later. </p>
<pre class="code"><span style="color: blue">public abstract class </span><span style="color: #2b91af">ExtendedFilterUserControl </span>: <span style="color: #2b91af">QueryableFilterUserControl
</span>{
    <span style="color: blue">private static readonly </span><span style="color: #2b91af">MethodInfo </span>initializeMethod =
        <span style="color: blue">typeof</span>(System.Web.DynamicData.<span style="color: #2b91af">QueryableFilterUserControl</span>)
        .GetMethod(<span style="color: #a31515">&quot;Initialize&quot;</span>,
            <span style="color: #2b91af">BindingFlags</span>.Instance | <span style="color: #2b91af">BindingFlags</span>.NonPublic);

    <span style="color: blue">private static readonly </span><span style="color: #2b91af">PropertyInfo </span>dataSourceProperty =
        <span style="color: blue">typeof</span>(System.Web.DynamicData.<span style="color: #2b91af">QueryableFilterUserControl</span>)
        .GetProperty(<span style="color: #a31515">&quot;QueryableDataSource&quot;</span>,
            <span style="color: #2b91af">BindingFlags</span>.Instance | <span style="color: #2b91af">BindingFlags</span>.NonPublic);

    <span style="color: blue">protected </span><span style="color: #2b91af">EntityDataSource </span>EntityDataSource
    {
        <span style="color: blue">get
        </span>{
            <span style="color: blue">return </span>(<span style="color: #2b91af">EntityDataSource</span>)dataSourceProperty.GetValue(<span style="color: blue">this</span>, <span style="color: blue">null</span>);
        }
    }

    <span style="color: blue">public void </span>Initialize(<span style="color: #2b91af">MetaColumn </span>metaColumn,
        <span style="color: #2b91af">IQueryableDataSource </span>dataSource, <span style="color: #2b91af">HttpContextBase </span>httpContext)
    {
        initializeMethod.Invoke(<span style="color: blue">this</span>,
            <span style="color: blue">new object</span>[] { metaColumn, dataSource, httpContext });
    }
}</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>This code uses reflection to access internal members of the <em>QueryableFilterUserControl</em> base class. This requires for the Dynamic Data application to be deployed with full trust, which increases security vulnerability of the web server and may not be possible in shared hosting environment. In order to take advantage of this new base class, we need to change all filter controls in the DynamicData\Filters folder of our project to inherit from <em>ExtendedFilterUserControl.</em></p>
<h4>Generating Joins Dynamically</h4>
</p>
<p><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a></p>
<p>If you remember, this is what an example of a static join query looked like with LINQ syntax.</p>
<pre class="code"><span style="color: blue">using </span>(<span style="color: #2b91af">NorthwindEntities </span>context = <span style="color: blue">new </span><span style="color: #2b91af">NorthwindEntities</span>())
{
    <span style="color: #2b91af">IQueryable</span>&lt;<span style="color: #2b91af">Customer</span>&gt; parentQuery = context.Customers;
    <span style="color: green">// generate where calls for parent query &#8230;

    </span><span style="color: #2b91af">IQueryable</span>&lt;<span style="color: #2b91af">Order</span>&gt; childQuery = context.Orders;
    <span style="color: green">// generate where calls for child query &#8230;

    </span><span style="color: blue">var </span>query = <span style="color: blue">from </span>customer <span style="color: blue">in </span>parentQuery
                <span style="color: blue">join </span>order <span style="color: blue">in </span>childQuery
                <span style="color: blue">on </span>customer.CustomerID <span style="color: blue">equals </span>order.CustomerID
                <span style="color: blue">select </span>order;

    <span style="color: #2b91af">Order</span>[] results = query.ToArray();
}</pre>
<p><a href="http://11011.net/software/vspaste"></a>However, we will need to generate joins dynamically, using LINQ expressions, which first requires us to understand how to implement joins using LINQ extension methods. Here is the same query implemented using the <a href="http://msdn.microsoft.com/en-us/library/system.linq.queryable.join.aspx" target="_blank">Join</a> extension method.</p>
<p><a href="http://11011.net/software/vspaste"></a></p>
<pre class="code"><span style="color: blue">using </span>(<span style="color: #2b91af">NorthwindEntities </span>context = <span style="color: blue">new </span><span style="color: #2b91af">NorthwindEntities</span>())
{
    <span style="color: #2b91af">IQueryable</span>&lt;<span style="color: #2b91af">Customer</span>&gt; parentQuery = context.Customers;
    <span style="color: green">// generate where calls for parent query &#8230;

    </span><span style="color: #2b91af">IQueryable</span>&lt;<span style="color: #2b91af">Order</span>&gt; childQuery = context.Orders;
    <span style="color: green">// generate where calls for child query &#8230;

    </span><span style="color: #2b91af">IQueryable</span>&lt;<span style="color: #2b91af">Order</span>&gt; query = parentQuery
        .Join(childQuery,
            customer =&gt; customer.CustomerID,
            order =&gt; order.CustomerID,
            (customer, order) =&gt; order);

    <span style="color: #2b91af">Order</span>[] results = query.ToArray();
}</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>Note that the on/equals clause of the LINQ join operator generates two lambda expressions called “key selectors”. A key selector takes an entity object, such as Customer, as a parameter and returns a “key value” that will be used to join the tables, such as CustomerID. The select clause of the LINQ join operator generates a lambda expression called “result selector”. A result selector takes two entities returned by the join and returns the entity that will be returned by the query, which in this case is Order.</p>
<p>This <em>Join</em> call is exactly what we need to generate dynamically in the <em>GetQueryable</em> method of our custom filter control.</p>
<pre class="code"><span style="color: blue">private </span><span style="color: #2b91af">ObjectContext </span>objectContext;
<span style="color: blue">private </span><span style="color: #2b91af">List</span>&lt;<span style="color: #2b91af">ExtendedFilterUserControl</span>&gt; filterControls;<span style="color: #2b91af">

</span><span style="color: blue">public override </span><span style="color: #2b91af">IQueryable </span>GetQueryable(<span style="color: #2b91af">IQueryable </span>sourceQuery)
{
    <span style="color: green">// Generate query against the parent table
    </span><span style="color: blue">var </span>foreignKeyColumn = (<span style="color: #2b91af">MetaForeignKeyColumn</span>)<span style="color: blue">this</span>.Column;
    <span style="color: #2b91af">MetaTable </span>parentTable = foreignKeyColumn.ParentTable;
    <span style="color: #2b91af">IQueryable </span>parentQuery = parentTable.GetQuery(<span style="color: blue">this</span>.objectContext);
    <span style="color: #2b91af">IQueryable </span>emptyParentQuery = parentQuery;
    <span style="color: blue">foreach </span>(<span style="color: blue">var </span>filterControl <span style="color: blue">in this</span>.filterControls)
    {
        parentQuery = filterControl.GetQueryable(parentQuery);
    }

    <span style="color: blue">if </span>(parentQuery != emptyParentQuery)
    {
        <span style="color: green">// Join the parent query with the main (child) query
        </span><span style="color: blue">string </span>primaryKeyColumnName = parentTable.PrimaryKeyColumns[0].Name;
        <span style="color: blue">string </span>foreignKeyColumnName = foreignKeyColumn.ForeignKeyNames[0];

        <span style="color: #2b91af">MethodCallExpression </span>joinCall = <span style="color: #2b91af">Expression</span>.Call(
            <span style="color: blue">typeof</span>(<span style="color: #2b91af">Queryable</span>),
            <span style="color: #a31515">&quot;Join&quot;</span>,
            <span style="color: blue">new </span><span style="color: #2b91af">Type</span>[] {
                    parentQuery.ElementType,
                    sourceQuery.ElementType,
                    <span style="color: blue">this</span>.Column.Table.GetColumn(foreignKeyColumnName).ColumnType,
                    sourceQuery.ElementType
                },
            <span style="color: blue">new </span><span style="color: #2b91af">Expression</span>[] {
                    parentQuery.Expression,
                    sourceQuery.Expression,
                    BuildKeySelector(parentQuery, primaryKeyColumnName),
                    BuildKeySelector(sourceQuery, foreignKeyColumnName),
                    BuildResultSelector(parentQuery, sourceQuery)
                }
        );
        sourceQuery = sourceQuery.Provider.CreateQuery(joinCall);
    }

    <span style="color: blue">return </span>sourceQuery;
}</pre>
<p>In the <em>GetQueryable </em>method, we use <a href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.metatable.aspx" target="_blank">MetaTable</a> class to create an empty parent query; iterate through the list of the filter controls and call their <em>GetQueryable</em> methods to allow them to add their <a href="http://msdn.microsoft.com/en-us/library/system.linq.queryable.where.aspx" target="_blank">Where</a> calls to the query. We then check the parent query to see if it was modified by any of the filter controls. If none of them modified the original parent query, i.e. if user has not entered any filter criteria for the parent table, we don’t have to do anything with the child (source) query. In fact, we don’t to modify the child query in this case because without parent filter criteria, we would only introduce an unnecessary join and reduce query performance.</p>
<p>Note that we pass an <a href="http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext.aspx" target="_blank">ObjectContext</a> to the <a href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.metatable.getquery.aspx" target="_blank">GetQuery</a> method of the parent <em>MetaTable.</em> In a LINQ <em>Join</em>, both queries must come from the same <em>ObjectContext</em> (in LINQ to Entities) or <a href="http://msdn.microsoft.com/en-us/library/system.data.linq.datacontext.aspx" target="_blank">DataContext</a> (in LINQ to SQL). We can get the right context using the <em>ContextCreated</em> event of the <a href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.entitydatasource.aspx" target="_blank">EntityDataSource</a> or the <a href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.linqdatasource.aspx" target="_blank">LinqDataSource</a> control used to perform the query. </p>
<pre class="code"><span style="color: blue">private </span><span style="color: #2b91af">ObjectContext </span>objectContext;

<span style="color: blue">protected override void </span>OnInit(<span style="color: #2b91af">EventArgs </span>e)
{
    <span style="color: blue">base</span>.OnInit(e);

<span style="color: green">    // &#8230;rest of the code&#8230; </span>

    <span style="color: blue">this</span>.EntityDataSource.ContextCreated += <span style="color: blue">this</span>.EntityDataSource_ContextCreated;
}

<span style="color: blue">private void </span>EntityDataSource_ContextCreated(<span style="color: blue">object </span>sender,
    <span style="color: #2b91af">EntityDataSourceContextCreatedEventArgs </span>e)
{
    <span style="color: blue">this</span>.objectContext = e.Context;
}</pre>
<p>And that is why we need to expose the internal <em>QueryableDataSource</em> property of <em>QueryableFilterUserControl</em> in our <em>ExtendedFilterUserControl</em> as shown above.</p>
<p>The code for <em>BuildKeySelector</em> and <em>BuildResultSelector</em> is relatively straightforward. The only counter-intuitive part you need to be aware of is that <a href="http://msdn.microsoft.com/en-us/library/system.linq.expressions.expression.lambda.aspx" target="_blank">Expression.Lambda</a> takes the body expression as it’s first parameter, followed by the parameter expressions.</p>
<pre class="code"><span style="color: blue">private static </span><span style="color: #2b91af">LambdaExpression </span>BuildKeySelector(<span style="color: #2b91af">IQueryable </span>query,
    <span style="color: blue">string </span>columnName)
{
    <span style="color: blue">var </span>parameter = <span style="color: #2b91af">Expression</span>.Parameter(query.ElementType);
    <span style="color: blue">var </span>property = <span style="color: #2b91af">Expression</span>.Property(parameter, columnName);
    <span style="color: blue">var </span>selector = <span style="color: #2b91af">Expression</span>.Lambda(property, parameter);
    <span style="color: blue">return </span>selector;
}

<span style="color: blue">private static </span><span style="color: #2b91af">LambdaExpression </span>BuildResultSelector(<span style="color: #2b91af">IQueryable </span>parentQuery,
    <span style="color: #2b91af">IQueryable </span>sourceQuery)
{
    <span style="color: blue">var </span>sourceParameter = <span style="color: #2b91af">Expression</span>.Parameter(sourceQuery.ElementType);
    <span style="color: blue">var </span>parentParameter = <span style="color: #2b91af">Expression</span>.Parameter(parentQuery.ElementType);
    <span style="color: blue">var </span>selector = <span style="color: #2b91af">Expression</span>.Lambda(sourceParameter,
        parentParameter, sourceParameter);
    <span style="color: blue">return </span>selector;
}</pre>
<h4>The Result</h4>
<p>Similar to other filter controls, all we need to do in order to take advantage of the new filter control is to apply a <a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.filteruihintattribute.aspx" target="_blank">FilterUIHint</a> to the appropriate foreign key columns in the model.</p>
<pre class="code">[<span style="color: #2b91af">MetadataType</span>(<span style="color: blue">typeof</span>(<span style="color: #2b91af">OrderDetail</span>.<span style="color: #2b91af">Metadata</span>))]
<span style="color: blue">public partial class </span><span style="color: #2b91af">OrderDetail
</span>{
    <span style="color: blue">public class </span><span style="color: #2b91af">Metadata
    </span>{
        [<span style="color: #2b91af">FilterUIHint</span>(<span style="color: #a31515">&quot;ParentTable&quot;</span>)]
        <span style="color: blue">public object </span>Order;
    }
}</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>Here is the search screen generated for the <em>OrderDetail</em> table before (left) and after (right) adding the <em>FilterUIHint </em>to the Order column.</p>
<table border="0" width="600">
<tbody>
<tr>
<td valign="top"><a href="http://www.olegsych.com/wp-content/uploads/2010/08/image1.png"><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/2010/08/image-thumb1.png" width="260" height="121" /></a> </td>
<td align="right"><a href="http://www.olegsych.com/wp-content/uploads/2010/08/image2.png"><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/2010/08/image-thumb2.png" width="260" height="204" /></a> </td>
</tr>
</tbody>
</table>
<p>As you can see, instead of a single drop-down list for selecting a single order, we now have a set of filter controls based on the columns of the parent (Order) table, including the custom <em>DateTimeFilter</em> controls we have implemented in the previous article. Obviously, there are several cosmetic problems, such as an orphaned “Order” label and a blank space between the parent table filter controls and the rest of the child table controls. We also don’t have the original <em>ForeignKey</em> filter control that was generated for the Order column before. For smaller reference tables, it may be beneficial to have the original foreign key filter in addition to the new parent filter controls, giving you the best of both worlds.</p>
<p>Fixing these problems is outside of scope of this article and is left as an exercise for the reader (tip: take a look at <a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.filteruihintattribute.controlparameters.aspx" target="_blank">FilterUIHintAttribute.ControlParameters</a> as one possible solution).</p>
<h5>Download</h5>
<p><a href="http://www.olegsych.com/wp-content/uploads/2010/08/dynamicdatademo.zip" target="_blank">Source Code</a>&#160; <br />See DynamicData\ExtendedFilterUserControl.cs and DynamicData\Filters\ParentTable.ascx.</p>
<p>&copy;2012 <a href="http://www.olegsych.com">Oleg Sych</a>. All Rights Reserved.</p>.<img src="http://feeds.feedburner.com/~r/olegsych/~4/cIY2eCdKXjo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.olegsych.com/2010/08/extending-aspnet-dynamic-data-filtering-with-joins/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Understanding ASP.NET Dynamic Data: Filter Templates</title>
		<link>http://www.olegsych.com/2010/07/understanding-aspnet-dynamic-data-filter-templates/</link>
		<comments>http://www.olegsych.com/2010/07/understanding-aspnet-dynamic-data-filter-templates/#comments</comments>
		<pubDate>Tue, 27 Jul 2010 12:47:28 +0000</pubDate>
		<dc:creator>Oleg Sych</dc:creator>
		
		<category><![CDATA[Articles]]></category>

		<category><![CDATA[Architecture]]></category>

		<category><![CDATA[ASP.NET]]></category>

		<category><![CDATA[Dynamic Data]]></category>

		<guid isPermaLink="false">http://www.olegsych.com/2010/07/understanding-aspnet-dynamic-data-filter-templates/</guid>
		<description><![CDATA[ASP.NET Dynamic Data lets you create extensible model-driven Web applications by inferring the appearance and behavior of entities from the model at run time. This article explains design of the dynamic filtering capabilities and demonstrates how to implement a custom filter template for DateTime data type.]]></description>
			<content:encoded><![CDATA[<p><a href="http://msdn.microsoft.com/en-us/library/ee845452.aspx">ASP.NET Dynamic Data</a> lets you create extensible model-driven Web applications by inferring the appearance and behavior of entities from the model at run time. It relies on “scaffolding” to automatically generate different types of Web pages for each entity in the model from a set of reusable ASP.NET user controls and pages. Each of these “templates” encapsulates a particular type of functionality, such as a filter control or a data entry form, and can be reused automatically for all entities in the model. ASP.NET Dynamic Data supports template scaffolding for pages, entities, fields and filters. A good step-by-step introduction can be found <a href="http://www.asp.net/aspnet-in-net-35-sp1/videos/aspnet-dynamic-data">here</a>. In this article we will be focusing on scaffolding of the filter templates.</p>
<h4>Queryable Data Sources</h4>
<p>Dynamic Data relies on LINQ and deferred query execution for filtering. Here is how we might go about filtering the list of orders in the <a target="_blank" href="http://www.microsoft.com/downloads/details.aspx?FamilyID=06616212-0356-46A0-8DA2-EEBC53A68034&amp;displaylang=en">Northwind</a> sample database to return only those placed after a given date using static code and the ADO.NET Entity Framework.</p>
<pre class="code"><span style="color: #2b91af">NorthwindEntities </span>context = <span style="color: blue">new </span><span style="color: #2b91af">NorthwindEntities</span>();
<span style="color: #2b91af">IQueryable</span>&lt;<span style="color: #2b91af">Order</span>&gt; query = context.Orders;
query = query.Where(order =&gt; order.OrderDate &gt; <span style="color: blue">new </span><span style="color: #2b91af">DateTime</span>(1996, 7, 15));
<span style="color: #2b91af">Order</span>[] orders = query.ToArray();</pre>
<p><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a></p>
<p>In line two of this example, we create a deferred query object that, when executed, would return all orders from the database. In line three, we replace the original query with a new one, which has a where clause to filter the orders based on the order date. Up until now, the query is stored in a form of a LINQ <a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.linq.expressions.expression.aspx">Expression</a> tree in memory of the executing program. Only in line four the ADO.NET Entity Framework transforms the query into a SQL SELECT statement and sends it to the database for execution. Once the response comes back from the database, the Entity Framework uses the returned data to create an array of <em>Order </em>objects.</p>
<p>Deferred query execution allows us to add practically any number of filters to the original query before it is sent to the database. Dynamic Data takes advantage of this powerful capability using the extensibility mechanisms built into the LINQ-based data source classes of ASP.NET 4.0 – <a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.linqdatasource.aspx">LinqDataSource</a> and <a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.entitydatasource.aspx">EntityDataSource</a>.</p>
<p><a href="http://www.olegsych.com/wp-content/uploads/2010/07/image.png"><img border="0" src="http://www.olegsych.com/wp-content/uploads/2010/07/image-thumb.png" alt="Queryable Data Source Class Diagram" style="display: inline; border-width: 0px" title="Queryable Data Source Class Diagram" height="305" width="600" /></a></p>
<p>Both of these classes implement the <a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.iqueryabledatasource.aspx">IQueryableDataSource</a> interface which exposes the <a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.iqueryabledatasource.querycreated.aspx">QueryCreated</a> event. A queryable data source object raises this event after it has created the original LINQ query, before sending it to the database. <em>QueryCreated</em> event handlers receive a <a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.querycreatedeventargs.aspx">QueryCreatedEventArgs</a> object which allows you to replace the original the original <a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.querycreatedeventargs.query.aspx">Query</a>, similar to how the code in line three of our example does.</p>
<p>To allow creating filters declaratively, using page markup, ASP.NET also provides a control called <a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.queryextender.aspx">QueryExtender</a>. <em>QueryExtender</em> is typically placed on a page and linked to a data source using <a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.queryextender.targetcontrolid.aspx">TargetControlID</a> property. Under the hood, the control handles the data source’s <em>QueryCreated</em> event and uses its own collection of <a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.expressions.datasourceexpression.aspx">DataSourceExpression</a> objects to modify the query.</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">EntityDataSource </span><span style="color: red">ID</span><span style="color: blue">=&#8221;dataSource&#8221; </span><span style="color: red">runat</span><span style="color: blue">=&#8221;server&#8221; </span><span style="color: blue">/&gt;
&lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">QueryExtender </span><span style="color: red">TargetControlID</span><span style="color: blue">=&#8221;dataSource&#8221; </span><span style="color: red">ID</span><span style="color: blue">=&#8221;queryExtender&#8221; </span><span style="color: red">runat</span><span style="color: blue">=&#8221;server&#8221;&gt;
    &lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">DynamicFilterExpression </span><span style="color: red">ControlID</span><span style="color: blue">=&#8221;filterRepeater&#8221; /&gt;
&lt;/</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">QueryExtender</span><span style="color: blue">&gt;</span></pre>
<p><em>DataSourceExpression </em>defines an abstract method called <a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.expressions.datasourceexpression.getqueryable.aspx">GetQueryable</a>. <em>QueryExtender</em> passes the original query to <em>GetQueryable</em> of first <em>DataSourceExpression</em>, takes the query it returns and passes it to the second <em>DataSourceExpression</em>, and so on, giving each expression the chance to modify the original query by adding a filter, changing its sort order, etc.</p>
<h4>Dynamic Filters</h4>
<p><a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.dynamicfilterexpression.aspx"><em>DynamicFilterExpression</em></a> inherits from the <em>DataSourceExpression</em> and overrides its <em>GetQueryable</em> method to take advantage of rich filter templating capabilities provided by the ASP.NET Dynamic Data. Using <a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.dynamicfilterexpression.controlid.aspx">ControlID</a> property, <em>DynamicFilterExpression</em> is typically associated with a <a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.queryablefilterrepeater.aspx">QueryableFilterRepeater</a>, another Dynamic Data control.</p>
<p><a href="http://11011.net/software/vspaste"></a></p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">QueryableFilterRepeater </span><span style="color: red">runat</span><span style="color: blue">=&#8221;server&#8221; </span><span style="color: red">ID</span><span style="color: blue">=&#8221;FilterRepeater&#8221;&gt;
  &lt;</span><span style="color: maroon">ItemTemplate</span><span style="color: blue">&gt;
    &lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">Label </span><span style="color: red">runat</span><span style="color: blue">=&#8221;server&#8221; </span><span style="color: red">Text</span><span style="color: blue">=&#8217;</span><span style="background: yellow">&lt;%</span><span style="color: blue"># </span>Eval(&#8221;DisplayName&#8221;) <span style="background: yellow">%&gt;</span><span style="color: blue">&#8216;
      </span><span style="color: red">OnPreRender</span><span style="color: blue">=&#8221;Label_PreRender&#8221; /&gt;
    &lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">DynamicFilter </span><span style="color: red">runat</span><span style="color: blue">=&#8221;server&#8221; </span><span style="color: red">ID</span><span style="color: blue">=&#8221;DynamicFilter&#8221;
      </span><span style="color: red">OnFilterChanged</span><span style="color: blue">=&#8221;DynamicFilter_FilterChanged&#8221; /&gt;
    &lt;</span><span style="color: maroon">br </span><span style="color: blue">/&gt;
  &lt;/</span><span style="color: maroon">ItemTemplate</span><span style="color: blue">&gt;
&lt;/</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">QueryableFilterRepeater</span><span style="color: blue">&gt;</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p><em>QueryableFilterRepeater</em> is a templated control, similar to the standard <a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.repeater.aspx">Repeater</a>. It generates a <a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.dynamicfilter.aspx">DynamicFilter</a> for each column in the queryable data source that can be filtered by Dynamic Data.</p>
<p><a href="http://www.olegsych.com/wp-content/uploads/2010/07/image1.png"><img border="0" src="http://www.olegsych.com/wp-content/uploads/2010/07/image-thumb1.png" alt="Dynamic Filter Class Diagram" style="display: inline; border-width: 0px" title="Dynamic Filter Class Diagram" height="433" width="600" /></a></p>
<p><em>DynamicFilter</em> control uses the filter scaffolding functionality of Dynamic Data to locate and load an appropriate user control from the ~/DynamicData/Filters folder of the web application. These user controls inherit from <a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.queryablefilterusercontrol.aspx">QueryableFilterUserControl</a>, a base class provided by Dynamic Data and designed for use with <em>DynamicFilter</em>.</p>
<p>Notice that all of the classes in the diagram above – <em>DynamicFilterExpression</em>, <em>QueryableFilterRepeater</em>, <em>DynamicFilter </em>and <em>QueryableFilterUserControl </em>– define a <em>GetQueryable </em>method that takes an <a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.linq.iqueryable.aspx">IQueryable</a> as a parameter and returns an <em>IQueryable</em>. At run time, the responsibility to modify the underlying LINQ query (an IQueryable instance) is passed from a <em>QueryExtender</em> all the way down the chain to a <em>QueryableFilterUserControl</em>, which was implemented to support filtering for a particular type of column, such as a Boolean or a foreign key.</p>
<p><a href="http://www.olegsych.com/wp-content/uploads/2010/07/image2.png"><img border="0" src="http://www.olegsych.com/wp-content/uploads/2010/07/image-thumb2.png" alt="GetQueryable Sequence Diagram" style="display: inline; border-width: 0px" title="GetQueryable Sequence Diagram" height="327" width="600" /></a></p>
<h4>Filter Controls</h4>
<p>Out of the box, ASP.NET Dynamic Data provides filter controls for Boolean, Enumeration and Foreign Key columns. This selection is rather limited, especially when you compare it to the wide range of edit controls available for the various column types. Luckily, creating a new filter template is relatively easy.</p>
<p>In the remainder of this article we will create a template filter for columns of <a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.datetime.aspx">DateTime</a> type. The filter control will allow users to filter date values based on a date value they enter and the operator they select, such as equals, before and after. The completed control will look similar to the picture below.</p>
<p><a href="http://www.olegsych.com/wp-content/uploads/2010/07/image3.png"><img border="0" src="http://www.olegsych.com/wp-content/uploads/2010/07/image-thumb3.png" alt="image" style="display: inline; border-width: 0px" title="image" height="50" width="234" /></a></p>
<ul>
<li>Add a new user control, <em>DateTime.ascx</em>, to the ~/DynamicData/Filters folder of your Dynamic Data web application. Name of the ASCX file is important, it will be used to provide a filter hint to Dynamic Data.</li>
</ul>
<pre class="code"><span style="background: yellow">&lt;%</span><span style="color: blue">@ </span><span style="color: maroon">Control </span><span style="color: red">Language</span><span style="color: blue">=&#8221;C#&#8221; </span><span style="color: red">CodeBehind</span><span style="color: blue">=&#8221;DateTime.ascx.cs&#8221;
  </span><span style="color: red">Inherits</span><span style="color: blue">=&#8221;DynamicDataDemo.DateFilter&#8221; </span><span style="background: yellow">%&gt; 

</span><span style="color: blue">&lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">DropDownList </span><span style="color: red">ID</span><span style="color: blue">=&#8221;dropDownList&#8221; </span><span style="color: red">runat</span><span style="color: blue">=&#8221;server&#8221; </span><span style="color: red">CssClass</span><span style="color: blue">=&#8221;DDFilter&#8221;&gt;
  &lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">ListItem </span><span style="color: red">Text</span><span style="color: blue">=&#8221;Equals&#8221; </span><span style="color: red">Value</span><span style="color: blue">=&#8221;==&#8221; /&gt;
  &lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">ListItem </span><span style="color: red">Text</span><span style="color: blue">=&#8221;Before&#8221; </span><span style="color: red">Value</span><span style="color: blue">=&#8221;&lt;&#8221; /&gt;
  &lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">ListItem </span><span style="color: red">Text</span><span style="color: blue">=&#8221;After&#8221; </span><span style="color: red">Value</span><span style="color: blue">=&#8221;&gt;&#8221; /&gt;
&lt;/</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">DropDownList</span><span style="color: blue">&gt; 

&lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">TextBox </span><span style="color: red">ID</span><span style="color: blue">=&#8221;textBox&#8221; </span><span style="color: red">runat</span><span style="color: blue">=&#8221;server&#8221; </span><span style="color: red">CssClass</span><span style="color: blue">=&#8221;DDTextBox&#8221; </span><span style="color: red">Columns</span><span style="color: blue">=&#8221;12&#8243; /&gt; 

&lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">CustomValidator </span><span style="color: red">ID</span><span style="color: blue">=&#8221;validator&#8221; </span><span style="color: red">runat</span><span style="color: blue">=&#8221;server&#8221; </span><span style="color: red">ControlToValidate</span><span style="color: blue">=&#8221;textBox&#8221;
  </span><span style="color: red">OnServerValidate</span><span style="color: blue">=&#8221;Validate&#8221; </span><span style="color: red">Text</span><span style="color: blue">=&#8221;*&#8221; </span><span style="color: red">CssClass</span><span style="color: blue">=&#8221;DDValidator&#8221;/&gt;</span></pre>
<p><a href="http://11011.net/software/vspaste"></a>In this ASCX, we have a drop-down list that displays a list of date operators the users can select from, and a text box, where they can enter a date value. The custom validator, used for the sake of simplicity, ensures that the value they enter in the text box is a valid date.</p>
<ul>
<li>In the code-behind file, change the base class from <em>UserControl</em> to <em>QueryableFilterUserControl</em>. Here is what it will look like at a glance.</li>
</ul>
<p><img border="0" src="http://www.olegsych.com/wp-content/uploads/2010/07/image4.png" alt="Code-behind File at a Glance" style="display: inline; border-width: 0px" title="Code-behind File at a Glance" height="364" width="544" /></p>
<ul>
<li><em>GetQueryable</em> is the main method in our filter control. Defined as abstract in the base class, this method is responsible for adding a filter to the query it receives.</li>
</ul>
<pre class="code"><span style="color: blue">public override </span><span style="color: #2b91af">IQueryable </span>GetQueryable(<span style="color: #2b91af">IQueryable </span>source)
{
  <span style="color: blue">if </span>(<span style="color: blue">string</span>.IsNullOrEmpty(<span style="color: blue">this</span>.textBox.Text) || !<span style="color: blue">this</span>.validator.IsValid)
  {
    <span style="color: blue">return </span>source;
  } 

  <span style="color: #2b91af">DateTime </span>date = <span style="color: #2b91af">DateTime</span>.Parse(<span style="color: blue">this</span>.textBox.Text);
  <span style="color: #2b91af">ConstantExpression </span>value = <span style="color: #2b91af">Expression</span>.Constant(date); 

  <span style="color: #2b91af">ParameterExpression </span>parameter = <span style="color: #2b91af">Expression</span>.Parameter(source.ElementType);
  <span style="color: #2b91af">MemberExpression </span>property = <span style="color: #2b91af">Expression</span>.Property(parameter, <span style="color: blue">this</span>.Column.Name);
  <span style="color: blue">if </span>(<span style="color: #2b91af">Nullable</span>.GetUnderlyingType(property.Type) != <span style="color: blue">null</span>)
  {
    property = <span style="color: #2b91af">Expression</span>.Property(property, <span style="color: #a31515">&#8220;Value&#8221;</span>);
  } 

  <span style="color: #2b91af">BinaryExpression </span>comparison;
  <span style="color: blue">switch </span>(<span style="color: blue">this</span>.dropDownList.SelectedValue)
  {
    <span style="color: blue">case </span><span style="color: #a31515">&#8220;==&#8221;</span>:
      comparison = <span style="color: #2b91af">Expression</span>.Equal(property, value);
      <span style="color: blue">break</span>;
    <span style="color: blue">case </span><span style="color: #a31515">&#8220;&gt;&#8221;</span>:
      comparison = <span style="color: #2b91af">Expression</span>.GreaterThan(property, value);
      <span style="color: blue">break</span>;
    <span style="color: blue">case </span><span style="color: #a31515">&#8220;&lt;&#8221;</span>:
      comparison = <span style="color: #2b91af">Expression</span>.LessThan(property, value);
      <span style="color: blue">break</span>;
    <span style="color: blue">default</span>:
      <span style="color: #2b91af">Debug</span>.Fail(<span style="color: #a31515">&#8220;Unexpected operator&#8221;</span>);
      <span style="color: blue">return </span>source;
  } 

  <span style="color: #2b91af">LambdaExpression </span>lambda = <span style="color: #2b91af">Expression</span>.Lambda(comparison, parameter); 

  <span style="color: #2b91af">MethodCallExpression </span>where = <span style="color: #2b91af">Expression</span>.Call(
    <span style="color: blue">typeof</span>(<span style="color: #2b91af">Queryable</span>),
    <span style="color: #a31515">&#8220;Where&#8221;</span>,
    <span style="color: blue">new </span><span style="color: #2b91af">Type</span>[] { source.ElementType },
    <span style="color: blue">new </span><span style="color: #2b91af">Expression</span>[] { source.Expression, <span style="color: #2b91af">Expression</span>.Quote(lambda) }); 

  <span style="color: blue">return </span>source.Provider.CreateQuery(where);
}</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>Unfortunately, because this control can be used for any <em>DateTime</em> column of any entity in our model, we cannot use strongly-typed code to implement this method. Instead of <em>IQueryable&lt;Order&gt;</em> we have to write code at the next level up - with the <em>IQueryable</em> interface and build the LINQ expression tree for our filter from the ground up. When expressed with strongly-typed code, the intent of this method could be distilled to the following pseudo-code:</p>
<pre class="code"><span style="color: #2b91af">IQueryable</span>&lt;<span style="color: #2b91af">Order</span>&gt; GetQueryable(<span style="color: #2b91af">IQueryable</span>&lt;<span style="color: #2b91af">Order</span>&gt; source)
{
  <span style="color: blue">if </span>(<span style="color: blue">string</span>.IsNullOrEmpty(<span style="color: blue">this</span>.textBox.Text) || !<span style="color: blue">this</span>.validator.IsValid)
  {
    <span style="color: blue">return </span>source;
  } 

  <span style="color: #2b91af">DateTime </span>date = <span style="color: #2b91af">DateTime</span>.Parse(<span style="color: blue">this</span>.textBox.Text); 

  <span style="color: #2b91af">Expression</span>&lt;Func&lt;<span style="color: #2b91af">Order</span>, <span style="color: blue">bool</span>&gt;&gt; lambda = <span style="color: blue">null</span>;
  <span style="color: blue">switch </span>(<span style="color: blue">this</span>.dropDownList.SelectedValue)
  {
    <span style="color: blue">case </span><span style="color: #a31515">&#8220;==&#8221;</span>:
      lambda = order =&gt; order.OrderDate == date;
      <span style="color: blue">break</span>;
    <span style="color: blue">case </span><span style="color: #a31515">&#8220;&gt;&#8221;</span>:
      lambda = order =&gt; order.OrderDate &gt; date;
      <span style="color: blue">break</span>;
    <span style="color: blue">case </span><span style="color: #a31515">&#8220;&lt;&#8221;</span>:
      lambda = order =&gt; order.OrderDate &lt; date;
      <span style="color: blue">break</span>;
    <span style="color: blue">default</span>:
      <span style="color: #2b91af">Debug</span>.Fail(<span style="color: #a31515">&#8220;Unexpected operator&#8221;</span>);
      <span style="color: blue">break</span>;
  } 

  <span style="color: blue">return </span>source.Where(lambda);
}</pre>
<p><a href="http://11011.net/software/vspaste"></a>As you can see in the actual implementation above, we have to explicitly perform all tasks the compiler would normally take care for us, such as declaring the parameter of the lambda expression, extracting the underlying value from a nullable property and calling the proper version of the generic Where method based on the entity type. When looking at the actual code above, remember that Where is an extension method defined by the <a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.linq.queryable.aspx">Queryable</a> class, and not by the <em>IQueryable</em> interface.</p>
<ul>
<li><em>FilterControl</em> property returns the control that should receive focus when user selects the <a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.label.aspx">Label</a> generated for it by the <em>QueryableFilterRepeater</em>. In our date filter, this can be either the drop-down list or the text box.</li>
</ul>
<pre class="code"><span style="color: blue">public override </span><span style="color: #2b91af">Control </span>FilterControl
{
  <span style="color: blue">get </span>{ <span style="color: blue">return this</span>.textBox; }
}</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<ul>
<li>The <em>Page_Load</em> event handler performs control initialization tasks that would be typically done declaratively, using markup in a regular filter form where information about columns being filtered is known at design time. In a Dynamic Data filter control, this information is available at run-time through the <a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.queryablefilterusercontrol.column.aspx">Column</a> property of the base class, which gives us a <a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.web.dynamicdata.metacolumn.aspx">MetaColumn</a> object describing the column for which our filter control was generated.</li>
</ul>
<pre class="code"><span style="color: blue">protected void </span>Page_Load(<span style="color: blue">object </span>sender, <span style="color: #2b91af">EventArgs </span>e)
{
  <span style="color: blue">this</span>.textBox.ToolTip = <span style="color: blue">this</span>.Column.Description;
  <span style="color: blue">this</span>.validator.ErrorMessage = <span style="color: #a31515">&#8220;Invalid date specified for &#8221; </span>+
      <span style="color: blue">this</span>.Column.DisplayName;
  <span style="color: blue">this</span>.validator.ToolTip = <span style="color: blue">this</span>.validator.ErrorMessage;
}</pre>
<p><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a></p>
<ul>
<li>And finally, the <em>Validate</em> method handles the server-side validation event of the <a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.customvalidator.aspx">CustomValidator</a> our control uses to ensure that a valid date was entered in the text box.</li>
</ul>
<pre class="code"><span style="color: blue">protected void </span>Validate(<span style="color: blue">object </span>sender, <span style="color: #2b91af">ServerValidateEventArgs </span>e)
{
  <span style="color: #2b91af">DateTime </span>value;
  e.IsValid = <span style="color: #2b91af">DateTime</span>.TryParse(e.Value, <span style="color: blue">out </span>value);
}</pre>
<h4>Filter Scaffolding</h4>
<p>Unlike for scaffolding of the data entry controls, ASP.NET Dynamic Data doesn’t use the same convention-based logic for filter controls. In order to instruct the framework to render a custom filter control for the <em>OrderDate</em> of our <em>Order</em> table, we need to mark the <em>OrderDate </em>property in our model with the <a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.filteruihintattribute(VS.95).aspx">FilterUIHintAttribute</a>.</p>
<ul>
<li>Add a new class to the project that contains your Entity Framework (EDMX) or LINQ to SQL (DBML) file and generated entity classes.</li>
</ul>
<p><a href="http://11011.net/software/vspaste"></a></p>
<pre class="code"><span style="color: blue">using </span>System.ComponentModel.DataAnnotations; 

<span style="color: blue">namespace </span>DynamicDataDemo
{
    [<span style="color: #2b91af">MetadataType</span>(<span style="color: blue">typeof</span>(<span style="color: #2b91af">Order</span>.<span style="color: #2b91af">Metadata</span>))]
    <span style="color: blue">partial class </span><span style="color: #2b91af">Order
    </span>{
        <span style="color: blue">public class </span><span style="color: #2b91af">Metadata
        </span>{
            [<span style="color: #2b91af">FilterUIHint</span>(<span style="color: #a31515">&#8220;DateTime&#8221;</span>)]
            <span style="color: blue">public object </span>OrderDate;
        }
    }
}</pre>
<p><a href="http://11011.net/software/vspaste"></a>Taking advantage of the fact that Entity Framework generates entity classes as partial, we can use <a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.metadatatypeattribute.aspx">MetadataTypeAttribute</a> to extend it with a custom metadata class and place an attribute on a property defined in the generated code without modifying generated code directly and risking loosing our changes the next time it is regenerated.</p>
<ul>
<li>Place a <em>FilterUIHintAttribute</em> on the property you want to have a filter control. The hint string you specify must match the name of the user control file (<em>DateTime.ascx</em>) without the extension.</li>
</ul>
<h4>Filter Criteria Change Notification</h4>
<p>If you are to run your ASP.NET Dynamic Data application now, you should be able to see the new filter for the <em>OrderDate </em>column on the <em>Orders/List.aspx</em> page. However, you will also notice that entering a date in the text box does not filter the results displayed in the grid automatically. This is because our data source control is not aware that filter criteria has changed and that query needs to be executed again. All built-in filter controls are drop-down lists and solve this problem by notifying the data source as soon as the selected value changes. Our custom filter uses a text box and cannot post back to server every time user presses a key when entering a date value. Instead, we will use a Search button to let the user perform the search when they are done with the criteria.</p>
<ul>
<li>Modify ~/DynamicData/PageTemplates/List.aspx to add a &#8220;Search” button just below the filter criteria.</li>
</ul>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">QueryableFilterRepeater </span><span style="color: red">runat</span><span style="color: blue">=&#8221;server&#8221; </span><span style="color: red">ID</span><span style="color: blue">=&#8221;FilterRepeater&#8221;&gt;
  &lt;</span><span style="color: maroon">ItemTemplate</span><span style="color: blue">&gt;
    &lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">Label </span><span style="color: red">runat</span><span style="color: blue">=&#8221;server&#8221; </span><span style="color: red">Text</span><span style="color: blue">=&#8217;</span><span style="background: yellow">&lt;%</span><span style="color: blue"># </span>Eval(&#8221;DisplayName&#8221;) <span style="background: yellow">%&gt;</span><span style="color: blue">&#8216;
      </span><span style="color: red">OnPreRender</span><span style="color: blue">=&#8221;Label_PreRender&#8221; /&gt;
    &lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">DynamicFilter </span><span style="color: red">runat</span><span style="color: blue">=&#8221;server&#8221; </span><span style="color: red">ID</span><span style="color: blue">=&#8221;DynamicFilter&#8221;
      </span><span style="color: red">OnFilterChanged</span><span style="color: blue">=&#8221;DynamicFilter_FilterChanged&#8221; /&gt;
    &lt;</span><span style="color: maroon">br </span><span style="color: blue">/&gt;
  &lt;/</span><span style="color: maroon">ItemTemplate</span><span style="color: blue">&gt;
&lt;/</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">QueryableFilterRepeater</span><span style="color: blue">&gt;
&lt;</span><span style="color: maroon">br </span><span style="color: blue">/&gt;
&lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">Button </span><span style="color: red">ID</span><span style="color: blue">=&#8221;searchButton&#8221; </span><span style="color: red">runat</span><span style="color: blue">=&#8221;server&#8221; </span><span style="color: red">Text</span><span style="color: blue">=&#8221;Search&#8221;
 </span><span style="color: red">OnClick</span><span style="color: blue">=&#8221;SearchButton_Click&#8221; /&gt;</span></pre>
<ul>
<li>Implement <em>SearchButton_Click</em> method in the code-behind file.</li>
</ul>
<pre class="code"><span style="color: blue">protected void </span>SearchButton_Click(<span style="color: blue">object </span>sender, <span style="color: #2b91af">EventArgs </span>e)
{
    ((<span style="color: #2b91af">IQueryableDataSource</span>)<span style="color: blue">this</span>.GridDataSource).RaiseViewChanged();
}</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>In this method, we are calling the <a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.iqueryabledatasource.raiseviewchanged.aspx">RaiseViewChanged</a> method of the <em>IQueryableDataSource </em>interface to let the data source know that it needs to re-execute the query. Unfortunately, <em>EntityDataSource</em> implements this interface explicitly, which requires a type cast before this method can be called.</p>
<p>Here is how the completed Order/List.aspx page looks after the user entered an order date and clicked the <em>Search </em>button. Note that in the entity model, <em>FilterUIHint</em> attributes were specified for <em>OrderDate</em>, <em>RequiredDate </em>and <em>ShippedDate </em>columns of the Orders table.</p>
<p> <img border="0" src="http://www.olegsych.com/wp-content/uploads/2010/07/image5.png" alt="Dynamic Data list page with date filters" style="display: inline; border: 0px" title="Dynamic Data list page with date filters" height="382" width="427" /></p>
<h4>Conclusion</h4>
<p>ASP.NET Dynamic Data provides powerful filtering capabilities that can be extended to fit needs of many data-driven web applications. Although creating dynamic filter controls is significantly more complex than creating statically typed controls, a dynamic filter control developed for a particular data type can be reused for any column of that type by simply applying the <em>FilterUIHintAttribute</em> to the property representing that column in the model. Unfortunately, Dynamic Data does not use the same convention-based logic for scaffolding of filter controls that it uses for scaffolding of data entry controls. This limitation requires you to explicitly place the <em>FilterUIHintAttribute</em> on every column instead of relying on the framework to infer this information based on the column type.</p>
<h5>Download</h5>
<ul>
<li><a href="http://www.olegsych.com/wp-content/uploads/2010/07/dynamicdatademo.zip">Sample source code</a>.</li>
</ul>
<p>&copy;2012 <a href="http://www.olegsych.com">Oleg Sych</a>. All Rights Reserved.</p>.<img src="http://feeds.feedburner.com/~r/olegsych/~4/LCbjoY_kAf8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.olegsych.com/2010/07/understanding-aspnet-dynamic-data-filter-templates/feed/</wfw:commentRss>
		</item>
		<item>
		<title>MSDN Radio: Code Generation with T4 and Visual Studio 2010</title>
		<link>http://www.olegsych.com/2010/06/msdn-radio-code-generation-with-t4-and-visual-studio-2010/</link>
		<comments>http://www.olegsych.com/2010/06/msdn-radio-code-generation-with-t4-and-visual-studio-2010/#comments</comments>
		<pubDate>Thu, 24 Jun 2010 14:15:24 +0000</pubDate>
		<dc:creator>Oleg Sych</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.olegsych.com/2010/06/msdn-radio-code-generation-with-t4-and-visual-studio-2010/</guid>
		<description><![CDATA[On June 28, I had a chance to chat with Zain Naboulsi on MSDN Radio about code generation, T4 and Visual Studio 2010. 
MSDN Radio is a weekly developer talk-show that helps answer your questions about the latest Microsoft news, solutions, and technologies. We dive into the challenges of deciphering today’s technology stack. Click here [...]]]></description>
			<content:encoded><![CDATA[<p>On June 28, I had a chance to chat with <a href="http://blogs.msdn.com/b/zainnab/">Zain Naboulsi</a> on MSDN Radio about code generation, T4 and Visual Studio 2010. </p>
<p><a href="http://www.msdnradio.com">MSDN Radio</a> is a weekly developer talk-show that helps answer your questions about the latest Microsoft news, solutions, and technologies. We dive into the challenges of deciphering today’s technology stack. Click <a href="http://channel9.msdn.com/posts/egibson/MSDN-Radio-Code-Generation-with-T4-and-Visual-Studio-with-Oleg-Sych/">here</a> to listen to the recording.</p>
<p>&copy;2012 <a href="http://www.olegsych.com">Oleg Sych</a>. All Rights Reserved.</p>.<img src="http://feeds.feedburner.com/~r/olegsych/~4/rkXU9O87E8M" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.olegsych.com/2010/06/msdn-radio-code-generation-with-t4-and-visual-studio-2010/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Understanding T4: &lt;#@ parameter #&gt; directive</title>
		<link>http://www.olegsych.com/2010/05/t4-parameter-directive/</link>
		<comments>http://www.olegsych.com/2010/05/t4-parameter-directive/#comments</comments>
		<pubDate>Mon, 10 May 2010 00:48:45 +0000</pubDate>
		<dc:creator>Oleg Sych</dc:creator>
		
		<category><![CDATA[Articles]]></category>

		<category><![CDATA[C#]]></category>

		<category><![CDATA[Code Generation]]></category>

		<category><![CDATA[T4]]></category>

		<category><![CDATA[Visual Basic]]></category>

		<category><![CDATA[Visual Studio]]></category>

		<guid isPermaLink="false">http://www.olegsych.com/2010/05/t4-parameter-directive/</guid>
		<description><![CDATA[Visual Studio 2010 introduced a new T4 directive called parameter. This directive provides a standard method for defining input parameters in text templates as well as passing parameter values at run time.]]></description>
			<content:encoded><![CDATA[<p>Visual Studio 2010 introduced a new <a href="http://www.olegsych.com/2007/12/text-template-transformation-toolkit/" target="_blank">T4</a> directive called <em>parameter</em>. This directive provides a standard method for defining input parameters in text templates as well as passing parameter values at run time. </p>
<h4>Syntax</h4>
<pre style="background-color: white" class="code"><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #a52a2a"> parameter </span><span style="color: #ff0000">name</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">&#8230;</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="color: #ff0000">type</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">&#8230;</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span></pre>
<h5>name</h5>
<p>Specifies name of the parameter and must be a valid <a href="http://msdn.microsoft.com/en-us/library/aa664670(VS.71).aspx" target="_blank">C#</a> or <a href="http://msdn.microsoft.com/en-us/library/aa711644(VS.71).aspx" target="_blank">Visual Basic</a> identifier.</p>
<h5>type</h5>
<p>Specifies type of the parameter and must include the complete namespace, such as System.String or System.Int32. A custom type can be used as well, as long as the assembly it is defined in is referenced with an <a href="http://www.olegsych.com/2008/02/t4-assembly-directive/" target="_blank">assembly directive</a> in the template.</p>
<h4>Usage</h4>
<p>During template transformation, parameters are available in template code as strongly-typed, read-only properties.</p>
<h6>MyTemplate.tt</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">template</span><span style="color: #000000"> </span><span style="color: #ff0000">language</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">C#</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #a52a2a"> parameter </span><span style="color: #ff0000">name</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">MyParameter</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="color: #ff0000">type</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">System.String</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
Parameter in expression block: </span><span style="background-color: #ffd700; color: #000000">&lt;#=</span><span style="background-color: #ffffe0; color: #000000"> MyParameter </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
Parameter in statement block: </span><span style="background-color: #ffd700; color: #000000">&lt;#</span><span style="background-color: #ffffe0; color: #000000"> Write(MyParameter) </span><span style="background-color: #ffd700; color: #000000">#&gt;</span></pre>
<p>Parameter values can be supplied via remoting <a href="http://msdn.microsoft.com/en-us/library/system.runtime.remoting.messaging.callcontext.aspx" target="_blank">CallContext</a> or the template transformation <a href="http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.texttemplating.texttransformation.session.aspx" target="_blank">Session</a>. Typically, this would be done in a Visual Studio extension that hosts its own instance of T4 engine or relies on the standard <a href="http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.texttemplating.vshost.itexttemplating.aspx" target="_blank">ITextTemplating</a> service. While Visual Studio extensions are a fascinating subject, its discussion is outside of scope of this article. Instead, we will illustrate the technique of passing parameter values using template code itself.</p>
<h5>Remoting CallContext</h5>
<p><a href="http://msdn.microsoft.com/en-us/library/system.runtime.remoting.messaging.callcontext.aspx" target="_blank">CallContext</a> allows you to define global variables whose scope is limited to a single thread, also known as thread-local variables. While on the surface the CallContext is similar to Thread Local Storage in Windows, when a remoting call is made, whether across the network or simply from one <a href="http://msdn.microsoft.com/en-us/library/system.appdomain.aspx" target="_blank">AppDomain</a> to another, the <a href="http://msdn.microsoft.com/en-us/library/system.runtime.remoting.messaging.logicalcallcontext.aspx" target="_blank">LogicalCallContext</a> travels with the call. In other words, CallContext allows you to define thread-local variables that will work even with remote calls. </p>
<p>In Visual Studio, T4 templates are <a href="http://www.olegsych.com/2008/05/t4-architecture/" target="_blank">normally executed in a separate AppDomain</a>, which is periodically unloaded to free memory. Therefore, remoting CallContext is a great way to specify template parameter values. The following example illustrates this can be done for the template shown above.</p>
<h6>CallContextTemplate.tt</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">template</span><span style="color: #000000"> </span><span style="color: #ff0000">language</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">C#</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="color: #ff0000">hostspecific</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">true</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">output</span><span style="color: #000000"> </span><span style="color: #ff0000">extension</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">.txt</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">import</span><span style="color: #000000"> </span><span style="color: #ff0000">namespace</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">System.IO</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">import</span><span style="color: #000000"> </span><span style="color: #ff0000">namespace</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">System.Runtime.Remoting.Messaging</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">import</span><span style="color: #000000"> </span><span style="color: #ff0000">namespace</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">Microsoft.VisualStudio.TextTemplating</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#</span><span style="background-color: #ffffff; color: #000000">
  </span><span style="background-color: #ffffe0; color: #0000ff">string</span><span style="background-color: #ffffe0; color: #000000"> templateFile = </span><span style="background-color: #ffffe0; color: #0000ff">this</span><span style="background-color: #ffffe0; color: #000000">.Host.ResolvePath(</span><span style="background-color: #ffffe0; color: #800000">&quot;MyTemplate.tt&quot;</span><span style="background-color: #ffffe0; color: #000000">);
  </span><span style="background-color: #ffffe0; color: #0000ff">string</span><span style="background-color: #ffffe0; color: #000000"> templateContent = File.ReadAllText(templateFile);

  CallContext.LogicalSetData(</span><span style="background-color: #ffffe0; color: #800000">&quot;MyParameter&quot;</span><span style="background-color: #ffffe0; color: #000000">, </span><span style="background-color: #ffffe0; color: #800000">&quot;CallContextValue&quot;</span><span style="background-color: #ffffe0; color: #000000">);

  Engine engine = </span><span style="background-color: #ffffe0; color: #0000ff">new</span><span style="background-color: #ffffe0; color: #000000"> Engine();
  </span><span style="background-color: #ffffe0; color: #0000ff">string</span><span style="background-color: #ffffe0; color: #000000"> generatedContent = engine.ProcessTemplate(templateContent, </span><span style="background-color: #ffffe0; color: #0000ff">this</span><span style="background-color: #ffffe0; color: #000000">.Host);

  CallContext.FreeNamedDataSlot(</span><span style="background-color: #ffffe0; color: #800000">&quot;MyParameter&quot;</span><span style="background-color: #ffffe0; color: #000000">);

  </span><span style="background-color: #ffffe0; color: #0000ff">this</span><span style="background-color: #ffffe0; color: #000000">.Write(generatedContent);
</span><span style="background-color: #ffd700; color: #000000">#&gt;</span></pre>
<h5>Template Transformation Session</h5>
<p>In Visual Studio 2010, T4 also allows you to access template transformation <a href="http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.texttemplating.texttransformation.session.aspx" target="_blank">Session</a> similar to the <a href="http://msdn.microsoft.com/en-us/library/system.web.ui.page.session.aspx" target="_blank">Session</a> in ASP.NET. Template transformation session allows you to define variables global for a particular template. Session variables can be passed from the transformation host to the template and can be used to define template parameter values. Here is how this can be done for the template shown above.</p>
<h6>SessionTemplate.tt</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">template</span><span style="color: #000000"> </span><span style="color: #ff0000">debug</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">true</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="color: #ff0000">hostspecific</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">true</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="color: #ff0000">language</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">C#</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">output</span><span style="color: #000000"> </span><span style="color: #ff0000">extension</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">.txt</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">import</span><span style="color: #000000"> </span><span style="color: #ff0000">namespace</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">System.IO</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">import</span><span style="color: #000000"> </span><span style="color: #ff0000">namespace</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">Microsoft.VisualStudio.TextTemplating</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#</span><span style="background-color: #ffffff; color: #000000">
  </span><span style="background-color: #ffffe0; color: #0000ff">string</span><span style="background-color: #ffffe0; color: #000000"> templateFile = </span><span style="background-color: #ffffe0; color: #0000ff">this</span><span style="background-color: #ffffe0; color: #000000">.Host.ResolvePath(</span><span style="background-color: #ffffe0; color: #800000">&quot;MyTemplate.tt&quot;</span><span style="background-color: #ffffe0; color: #000000">);
  </span><span style="background-color: #ffffe0; color: #0000ff">string</span><span style="background-color: #ffffe0; color: #000000"> templateContent = File.ReadAllText(templateFile);

  TextTemplatingSession session = </span><span style="background-color: #ffffe0; color: #0000ff">new</span><span style="background-color: #ffffe0; color: #000000"> TextTemplatingSession();
  session[</span><span style="background-color: #ffffe0; color: #800000">&quot;MyParameter&quot;</span><span style="background-color: #ffffe0; color: #000000">] = </span><span style="background-color: #ffffe0; color: #800000">&quot;SessionValue&quot;</span><span style="background-color: #ffffe0; color: #000000">;

  </span><span style="background-color: #ffffe0; color: #0000ff">var</span><span style="background-color: #ffffe0; color: #000000"> sessionHost = (ITextTemplatingSessionHost) </span><span style="background-color: #ffffe0; color: #0000ff">this</span><span style="background-color: #ffffe0; color: #000000">.Host;
  sessionHost.Session = session;

  Engine engine = </span><span style="background-color: #ffffe0; color: #0000ff">new</span><span style="background-color: #ffffe0; color: #000000"> Engine();
  </span><span style="background-color: #ffffe0; color: #0000ff">string</span><span style="background-color: #ffffe0; color: #000000"> generatedContent = engine.ProcessTemplate(templateContent, </span><span style="background-color: #ffffe0; color: #0000ff">this</span><span style="background-color: #ffffe0; color: #000000">.Host);

  </span><span style="background-color: #ffffe0; color: #0000ff">this</span><span style="background-color: #ffffe0; color: #000000">.Write(generatedContent);
</span><span style="background-color: #ffd700; color: #000000">#&gt;</span></pre>
<h4>Under the Hood</h4>
<p>T4 engine generates a private, read-only property for each parameter directive in your template. In particular, here is how the template shown above is compiled by T4.</p>
<pre class="code"><span style="color: blue">public partial class </span><span style="color: #2b91af">MyTemplate </span>: <span style="color: #2b91af">TextTransformation
</span>{
    <span style="color: blue">private string </span>_MyParameterField;
    <span style="color: blue">private string </span>MyParameter
    {
        <span style="color: blue">get </span>{ <span style="color: blue">return this</span>._MyParameterField; }
    }

    <span style="color: blue">public override string </span>TransformText()
    {
        <span style="color: blue">this</span>.GenerationEnvironment = <span style="color: blue">null</span>;
        <span style="color: blue">this</span>.Write(<span style="color: #a31515">&quot;Parameter in expression block: &quot;</span>);
        <span style="color: blue">this</span>.Write(<span style="color: blue">this</span>.ToStringHelper.ToStringWithCulture(MyParameter));

        <span style="color: blue">this</span>.Write(<span style="color: #a31515">&quot;\r\nParameter in statement block: &quot;</span>);
        Write(MyParameter);

        <span style="color: blue">return this</span>.GenerationEnvironment.ToString();
    }

    <span style="color: green">// &#8230;
</span>}</pre>
<p>Notice that <em>MyParameter</em> property is backed by a private field. The field is initialized by code in the <em>Initialize </em>method, invoked by T4 before the <em>TransformText </em>method which performs the actual code generation. </p>
<p><a href="http://11011.net/software/vspaste"></a></p>
<pre class="code"><span style="color: blue">public partial class </span><span style="color: #2b91af">MyTemplate </span>: <span style="color: #2b91af">TextTransformation
</span>{
  <span style="color: green">// &#8230;

  </span><span style="color: blue">public override void </span>Initialize()
  {
    <span style="color: blue">base</span>.Initialize();
    <span style="color: blue">if </span>(<span style="color: blue">this</span>.Errors.HasErrors == <span style="color: blue">false</span>)
    {
      <span style="color: blue">bool </span>MyParameterValueAcquired = <span style="color: blue">false</span>;
      <span style="color: blue">if </span>(<span style="color: blue">this</span>.Session.ContainsKey(<span style="color: #a31515">&quot;MyParameter&quot;</span>))
      {
        <span style="color: blue">if </span>(<span style="color: blue">typeof</span>(<span style="color: blue">string</span>).IsAssignableFrom(<span style="color: blue">this</span>.Session[<span style="color: #a31515">&quot;MyParameter&quot;</span>].GetType()) == <span style="color: blue">false</span>)
        {
          <span style="color: blue">this</span>.Error(<span style="color: #a31515">&quot;The type \&#8217;System.String\&#8217; of the parameter \&#8217;MyParameter\&#8217; did not match the type of&quot; </span>+
              <span style="color: #a31515">&quot; the data passed to the template.&quot;</span>);
        }
        <span style="color: blue">else
        </span>{
          <span style="color: blue">this</span>._MyParameterField = (<span style="color: blue">string</span>)<span style="color: blue">this</span>.Session[<span style="color: #a31515">&quot;MyParameter&quot;</span>];
          MyParameterValueAcquired = <span style="color: blue">true</span>;
        }
      }

      <span style="color: blue">if </span>(MyParameterValueAcquired == <span style="color: blue">false</span>)
      {
        <span style="color: blue">object </span>data = <span style="color: #2b91af">CallContext</span>.LogicalGetData(<span style="color: #a31515">&quot;MyParameter&quot;</span>);
        <span style="color: blue">if </span>(data != <span style="color: blue">null</span>)
        {
          <span style="color: blue">if </span>(<span style="color: blue">typeof</span>(<span style="color: blue">string</span>).IsAssignableFrom(data.GetType()) == <span style="color: blue">false</span>)
          {
            <span style="color: blue">this</span>.Error(<span style="color: #a31515">&quot;The type \&#8217;System.String\&#8217; of the parameter \&#8217;MyParameter\&#8217; did not match the type of&quot; </span>+
                <span style="color: #a31515">&quot; the data passed to the template.&quot;</span>);
          }
          <span style="color: blue">else
          </span>{
            <span style="color: blue">this</span>._MyParameterField = (<span style="color: blue">string</span>)data;
          }
        }
      }
    }
  }

  <span style="color: green">// &#8230;
</span>}</pre>
<p>As you can see, the template will first try to retrieve the parameter value from its <em>Session</em>, and only if it doesn’t exist there, it will try the remoting <em>CallContext</em>.</p>
<h4>Closing Thoughts</h4>
<p>Parameter directive closes an important gap in the integration story of T4. In the past, most notably in ASP.NET MVC, this gap lead the tool developers using T4 down the wrong path of creating a custom <a href="http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.texttemplating.itexttemplatingenginehost.aspx" target="_blank">ITextTemplatingEngineHost</a> just to be able to pass parameters from the tool to the template. Although the remoting <em>CallContext</em> was available before and template parameters are just a thin wrapper around it, this new mechanism will be difficult to miss now that it is a part of the template syntax. Unfortunately, this may have come too late for MVC, which is bound by backward compatibility chains to the old custom host, making it impossible to use any but the limited, MVC-specific templates with this tool.</p>
<p><a href="http://11011.net/software/vspaste"></a></p>
<h4>References</h4>
<ul>
<li><a href="http://blogs.appventure.com/Kathleen/2009/10/22/T4TemplatesNativelySupportParameters.aspx" target="_blank">T4 Templates Natively Support Parameters</a> by Kathleen Dollard </li>
<li><a href="http://blogs.msdn.com/garethj/archive/2010/04/15/what-s-new-in-t4-in-visual-studio-2010.aspx" target="_blank">What’s new in T4 in Visual Studio 2010</a> by Gareth Jones </li>
</ul>
<p>&copy;2012 <a href="http://www.olegsych.com">Oleg Sych</a>. All Rights Reserved.</p>.<img src="http://feeds.feedburner.com/~r/olegsych/~4/VIcgztEC2ho" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.olegsych.com/2010/05/t4-parameter-directive/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Understanding T4: MSBuild Integration</title>
		<link>http://www.olegsych.com/2010/04/understanding-t4-msbuild-integration/</link>
		<comments>http://www.olegsych.com/2010/04/understanding-t4-msbuild-integration/#comments</comments>
		<pubDate>Sun, 11 Apr 2010 23:44:29 +0000</pubDate>
		<dc:creator>Oleg Sych</dc:creator>
		
		<category><![CDATA[Articles]]></category>

		<category><![CDATA[C#]]></category>

		<category><![CDATA[Code Generation]]></category>

		<category><![CDATA[MSBuild]]></category>

		<category><![CDATA[T4]]></category>

		<category><![CDATA[Visual Basic]]></category>

		<category><![CDATA[Visual Studio]]></category>

		<guid isPermaLink="false">http://www.olegsych.com/2010/04/understanding-t4-msbuild-integration/</guid>
		<description><![CDATA[This article describes the new capability offered by Visual Studio 2010 to perform template-based code generation at build-time, with the help of a set of MSBuild extensions available as part of the Visualization and Modeling SDK.]]></description>
			<content:encoded><![CDATA[<p>Visual Studio 2010 offers a new capability to perform template-based code generation at build-time with a set of MSBuild extensions available as part of the Visualization and Modeling SDK. </p>
<h4>Contents</h4>
<ul>
<li><a href="#Overview">Overview</a> </li>
<li><a href="#ConfiguringProject">Configuring project for build-time template transformation</a> </li>
<li><a href="#UnderTheHood">Under the hood</a> </li>
<li><a href="#ProjectAndSourceControlIntegration">Project and Source Control Integration</a> </li>
<li><a href="#ConfiguringTransformationEnvironment">Configuring transformation environment</a>
<ul>
<li><a href="#IncludeFolders">$(IncludeFolders) property</a> </li>
<li><a href="#T4ReferencePath">@(T4ReferencePath) items</a> </li>
<li><a href="#DirectiveProcessor">@(DirectiveProcessor) items</a> </li>
<li><a href="#T4ParameterValues">@(T4ParameterValues) items</a> </li>
<li><a href="#OutputFilePath">.OutputFilePath metadata</a> </li>
<li><a href="#OutputFileName">.OutputFileName metadata</a> </li>
<li><a href="#InludeDslT4Settings">$(IncludeDslT4Settings) property</a> </li>
</ul>
</li>
<li><a href="#ControllingTransformationProcess">Controlling transformation process</a>
<ul>
<li><a href="#TransformOnBuild">$(TransformOnBuild) property</a> </li>
<li><a href="#TransformOutOfDateOnly">$(TransformOutOfDateOnly) property</a> </li>
<li><a href="#TrackFileAccess">$(TrackFileAccess) property</a> </li>
<li><a href="#OverwriteReadOnlyOutputFiles">$(OverwriteReadOnlyOutputFiles) property</a> </li>
<li><a href="#BeforeTransform">$(BeforeTransform) property</a> </li>
<li><a href="#AfterTransform">$(AfterTransform) property</a> </li>
<li><a href="#GeneratedFiles">@(GeneratedFiles) items</a> </li>
<li><a href="#NonGeneratedFiles">@(NonGeneratedFiles) items</a> </li>
</ul>
</li>
<li><a href="#CallingMSBuildExplicitly">Transforming templates by calling MSBuild explicitly</a>
<ul>
<li><a href="#TransformAll">TransformAll target</a> </li>
<li><a href="#Transform">Transform target</a> </li>
</ul>
</li>
<li><a href="#Conclusion">Conclusion</a> </li>
<li><a href="#Download">Download</a> </li>
</ul>
<h4 id="Overview">Overview</h4>
<p>Since its initial release, <a href="http://www.olegsych.com/2007/12/text-template-transformation-toolkit/" target="_blank">T4</a> has followed a well-established pattern of integrating code generators in Visual Studio and providing two different ways to generate code. The first and primary method of triggering template transformation process is at design time, by saving the template file. When a template (.tt) file is added to a C# or Visual Basic project, it is automatically associated with a <a href="http://msdn.microsoft.com/en-us/library/bb166817.aspx" target="_blank">custom tool</a> called <em>TextTemplatingFileGenerator</em>. Visual Studio invokes the custom tool whenever the associated file is saved, causing the output file to be regenerated whenever the template file is modified. The second and alternative method of triggering template transformation process is at build time, with a command line utility called <a href="http://msdn.microsoft.com/en-us/library/bb126245.aspx" target="_blank">TextTransform</a>. In order to generate code at build time, a developer needs to modify the MSBuild definition of a Visual Studio project and invoke this command utility for each of the template files that need to be transformed.</p>
<p>The main benefits of design-time code generation are its simplicity and automatic addition of the generated files in Visual Studio projects and source control. This approach works well when template files are self contained. However, when templates <a href="http://www.olegsych.com/2008/02/t4-include-directive/" target="_blank">include</a> other files or use external sources of metadata, such as model files or databases, the generated files may become out of date even if their templates don’t change. Build-time code generation ensures that output files are always current and makes sense in complex scenarios when keeping track of multiple templates becomes error prone. The main drawbacks of build-time code generation are the additional effort required to implement it, and more importantly, the set of challenges it presents around integration with Visual Studio projects and source control.</p>
<p>Visual Studio 2010 offers a new option for generating code from <a href="http://www.olegsych.com/2007/12/text-template-transformation-toolkit/" target="_blank">text templates</a> at build time. This capability is implemented as a set of <a href="http://msdn.microsoft.com/en-us/library/wea2sca5.aspx" target="_blank">MSBuild</a> tasks and targets that come with the <a href="http://code.msdn.microsoft.com/vsvmsdk" target="_blank">Visual Studio Modeling and Visualization SDK</a>. Here is where the files are located.</p>
<pre class="code">C:\&gt;dir &quot;C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\TextTemplating\v10.0&quot; /b
Microsoft.TextTemplating.Build.Tasks.dll
Microsoft.TextTemplating.targets
Microsoft.VisualStudio.TextTemplating.Sdk.Host.10.0.dll</pre>
<p>The new MSBuild integration feature of T4 significantly reduces the effort required to implement and maintain build-time code generation and solves some of the challenges around integration with Visual Studio projects and source control. </p>
<h4 id="ConfiguringProject">Configuring project for build-time template transformation</h4>
<p>In order to configure a Visual Studio project for build-time template transformation, you have to manually modify the MSBuild definition in the project file. At a minimum, you need to import <em>Microsoft.TextTemplating.targets</em> file and set <em>TransformOnBuild</em> property to true. Here is an extract from a C# project file that was modified this way.</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">Import </span><span style="color: red">Project</span><span style="color: blue">=</span>&quot;<span style="color: blue">$(MSBuildToolsPath)\Microsoft.CSharp.targets</span>&quot; <span style="color: blue">/&gt;
&lt;</span><span style="color: #a31515">PropertyGroup</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">TransformOnBuild</span><span style="color: blue">&gt;</span>true<span style="color: blue">&lt;/</span><span style="color: #a31515">TransformOnBuild</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">PropertyGroup</span><span style="color: blue">&gt;
&lt;</span><span style="color: #a31515">Import </span><span style="color: red">Project</span><span style="color: blue">=</span>&quot;<span style="color: blue">$(MSBuildExtensionsPath)\Microsoft\VisualStudio\TextTemplating\v10.0\Microsoft.TextTemplating.targets</span>&quot; <span style="color: blue">/&gt;
</span></pre>
<p>Note that <em>Microsoft.TextTemplating.targets</em> file has to be imported <em>after</em> the standard import – <em>Microsoft.CSharp.targets</em> for C# or <em>Microsoft.VisualBasic.targets </em>for Visual Basic projects. The TransformOnBuild variable can be defined anywhere in the file, such as in the main <em>PropertyGroup</em> of the project.</p>
<p>Here is a typical output you will see when building a customized project.</p>
<pre class="code">------ Build started: Project: T4MSBuild, Configuration: Debug x86 ------
Build started 4/10/2010 1:30:38 PM.
ExecuteTransformations:
  Performing incremental T4 transformation
  Calculating whether transformed output is out of date...
  Transforming template Template.tt...
  Performing incremental T4 preprocessing
  Calculating whether preprocessed output is out of date...
  Preprocessing template PreprocessedTemplate.tt...
GenerateTargetFrameworkMonikerAttribute:
Skipping target &quot;GenerateTargetFrameworkMonikerAttribute&quot; because all output files are up-to-date with respect to the input files.
CoreCompile:
  C:\Windows\Microsoft.NET\Framework\v4.0.30319\Csc.exe /noconfig /nowarn:1701,1702 /nostdlib+ /platform:x86 /reference:&quot;C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\mscorlib.dll&quot; /reference:&quot;C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Core.dll&quot; /reference:&quot;C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.dll&quot; /debug+ /out:obj\x86\Debug\T4MSBuild.dll /target:library PreprocessedTemplate.cs Template.cs &quot;C:\Users\osych\AppData\Local\Temp\.NETFramework,Version=v4.0.AssemblyAttributes.cs&quot;
CopyFilesToOutputDirectory:
  Copying file from &quot;obj\x86\Debug\T4MSBuild.dll&quot; to &quot;bin\Debug\T4MSBuild.dll&quot;.
  T4MSBuild -&gt; C:\T4MSBuild\T4MSBuild\bin\Debug\T4MSBuild.dll
  Copying file from &quot;obj\x86\Debug\T4MSBuild.pdb&quot; to &quot;bin\Debug\T4MSBuild.pdb&quot;.

Build succeeded.

Time Elapsed 00:00:00.55
========== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped ==========</pre>
<p><a href="http://11011.net/software/vspaste"></a>In this sample output, note that a file called <em>Template.tt</em> was transformed and another file called <em>PreprocessedTemplate.tt</em> was preprocessed. In other words, the MSBuild functionality fully supports the <a href="http://www.olegsych.com/2009/09/t4-preprocessed-text-templates/" target="_blank">preprocessed templates</a> introduced in Visual Studio 2010.</p>
<h4 id="UnderTheHood">Under the hood</h4>
<p>When imported, <em>Microsoft.TextTemplating.targets </em>file modifies the normal project build process defined in <em>Microsoft.Common.targets</em> by inserting the following steps (targets) in the beginning of the build sequence.</p>
<ul>
<li>Create a list of candidate files for transformation </li>
<li>Execute user-defined target before transformation </li>
<li>Select template files for processing </li>
<li>Transform and/or preprocess templates </li>
<li>Execute user-defined target after transformation </li>
</ul>
<p>T4 creates a list of candidate files for transformation by selecting <em>all</em> files in the project that have <a href="http://msdn.microsoft.com/en-us/library/0c6xyb66.aspx" target="_blank">build action</a> of <em>None</em>, <em>Compile</em>, <em>Content </em>or <em>EmbeddedResource</em>. Normally, .tt files have build action of <em>None</em> and get included automatically. </p>
<p>After the initial list of candidate files has been created, T4 invokes a user-defined target specified in the <em>$(BeforeTransform)</em> property. You can assign this property and provide a custom target if you need to perform any actions before the templates are processed.</p>
<p>After executing the user-defined <em>BeforeTransform </em>target, T4 will use the initial candidate list of files to select those associated with the <em>TextTemplatingFileGenerator</em> custom tool to be transformed in a set of items called <em>@(T4TransformInputs)</em> and those associated with the <em>TextTemplatingFilePreprocessor</em> custom tool to be pre-processed in a set of items called <em>@(T4PreprocessInputs)</em>. It is important to remember that template files are selected for processing based on their association with one of the T4’s custom tools; the file extension or build action have no effect in this process. </p>
<p>After determining the actual lists of templates, T4 transforms and pre-processes them. This is done by the MSBuild tasks called <em>TransformTemplates</em> and <em>PreprocessTemplates </em>implemented in <em>Microsoft.TextTemplating.Build.Tasks.dll</em>. These tasks use a <a href="http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.texttemplating.itexttemplatingenginehost.aspx" target="_blank">custom T4 host</a> implemented in <em>Microsoft.VisualStudio.TextTemplating.Sdk.Host.10.0.dll</em>. </p>
<p>In <a href="http://www.olegsych.com/2008/05/t4-architecture/">T4 architecture</a>,&#160; the host plays a very important role in the template transformation process. It provides the compilation and run-time environment for the code generation and determines how the included files are located, how the assembly references are resolved, how directive processors are selected and more. Each of the existing T4 hosts is implemented and configured differently, which can make them incompatible with templates that take advantage of the unique functionality of a particular host. For example, T4 templates in ASP.NET MVC and <a href="http://t4toolbox.codeplex.com/" target="_blank">T4 Toolbox</a> rely on the unique features of the MVC and Visual Studio hosts respectively. They are currently incompatible with the MSBuild host described here. </p>
<p>Even templates that don’t have hard-coded dependencies on a particular host will often require additional steps to configure the transformation environment before they can be processed by the MSBuild host. Detailed description of the configuration options is available later in this article.</p>
<p>After transforming and preprocessing templates, T4 invokes a second user-defined target specified in the <em>$(AfterTransform)</em> property. You can assign this variable and provide a custom target if you need to perform any actions when the templates are transformed but before the build starts.</p>
<h4 id="ProjectAndSourceControlIntegration">Project and Source Control Integration</h4>
<p>Unlike the standard Visual Studio host of T4, the MSBuild host described here does not integrate generated files with Visual Studio projects or source control. In particular, the generated files are not added to the project and source control automatically; the regenerated files are not checked out from source control automatically. This integration functionality relies on services provided by Visual Studio, which is not available in the MSBuild host.</p>
<p>Luckily, a limited awareness of source control exists in the MSBuild host of T4. By default, it will issue a warning for each read-only output file that could not be regenerated and an error, making sure that build will fail if one or more files could not be regenerated.</p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="" border="0" alt="" src="http://www.olegsych.com/wp-content/uploads/2010/04/image.png" width="580" height="176" /> </p>
<p>In order to resolve these errors, you can either locate and check out all required files manually, or transform all templates from the toolbar in Solution Explorer, which will process them using the Visual Studio host and check out all files automatically. Once the files have been regenerated, you will typically want to check them back in source control. </p>
<p>You can also instruct T4 to automatically overwrite read-only files during code generation by setting the <em>$(OverwriteReadOnlyOutputFiles) </em>property to true. </p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">PropertyGroup</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">TransformOnBuild</span><span style="color: blue">&gt;</span>true<span style="color: blue">&lt;/</span><span style="color: #a31515">TransformOnBuild</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">OverwriteReadOnlyOutputFiles</span><span style="color: blue">&gt;</span>true<span style="color: blue">&lt;/</span><span style="color: #a31515">OverwriteReadOnlyOutputFiles</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">PropertyGroup</span><span style="color: blue">&gt;
&lt;</span><span style="color: #a31515">Import </span><span style="color: red">Project</span><span style="color: blue">=</span>&quot;<span style="color: blue">$(MSBuildExtensionsPath)\Microsoft\VisualStudio\TextTemplating\v10.0\Microsoft.TextTemplating.targets</span>&quot; <span style="color: blue">/&gt;
</span></pre>
<p>This setting eliminates build errors, but introduces discrepancies between the code checked in the source control repository and the actual code compiled during the build. With this approach you can no longer rely on the source control repository alone to recreate a particular labeled build. If you want to debug or troubleshoot a particular build of the application later, you will have to save the complete source code in addition to the binary and symbol files produced by each build. This is necessary for all but trivial scenarios, and especially for packaged commercial software products and enterprise applications.</p>
<h4 id="ConfiguringTransformationEnvironment">Configuring transformation environment</h4>
<p>MSBuild functionality of T4 relies on a new engine host, which is different from both the default host used by the T4 custom tools in Visual Studio and the command line host used by <em>TextTransform.exe</em>. It relies on MSBuild items and properties to configure normal settings such as include search path, directive processors and assembly references, as well as settings unique to the MSBuild host. </p>
<h5 id="IncludeFolders">$(IncludeFolders) property</h5>
<p>Specifies a coma-separated list of directories that T4 will search to resolve files referenced by <a href="http://www.olegsych.com/2008/02/t4-include-directive/">include directives</a>. This property is empty by default.</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">PropertyGroup</span><span style="color: blue">&gt;
</span><span style="color: blue">  &lt;</span><span style="color: #a31515">IncludeFolders</span><span style="color: blue">&gt;</span>$(MSBuildProjectDirectory)\Include<span style="color: blue">&lt;/</span><span style="color: #a31515">IncludeFolders</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">PropertyGroup</span><span style="color: blue">&gt;
</span></pre>
<p><em>$(IncludeFolders)</em> property is an equivalent of the –I parameter of the <a href="http://msdn.microsoft.com/en-us/library/bb126245.aspx">command-line host</a> and the HKLM\Software\Microsoft\VisualStudio\10.0\TextTemplating\IncludeFolders registry setting of the Visual Studio host of T4. </p>
<h5 id="T4ReferencePath">@(T4ReferencePath) items</h5>
<p>Specify individual folders where T4 will search to resolve assemblies referenced by <a href="http://www.olegsych.com/2008/02/t4-assembly-directive/">assembly directives</a> and custom directive processors. This item list is empty by default. </p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">ItemGroup</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">T4ReferencePath </span><span style="color: red">Include</span><span style="color: blue">=</span>&quot;<span style="color: blue">$(VsInstallDir)PublicAssemblies\</span>&quot; <span style="color: blue">/&gt;
&lt;/</span><span style="color: #a31515">ItemGroup</span><span style="color: blue">&gt;</span></pre>
<p><em>@(T4ReferencePath)</em> items are an equivalent of the –P parameter of the <a href="http://msdn.microsoft.com/en-us/library/bb126245.aspx">command-line host</a> and have no direct equivalent in the Visual Studio host of T4, which uses global assembly cache, assemblies referenced by the project and some hard-coded search paths. </p>
<h5 id="DirectiveProcessor">@(DirectiveProcessor) items</h5>
<p>Specify definitions of the directive processors T4 will use when processing custom directives. This item list is empty by default.</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">ItemGroup</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">DirectiveProcessor </span><span style="color: red">Include</span><span style="color: blue">=</span>&quot;<span style="color: blue">T4Toolbox.XsdProcessor</span>&quot; <span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">Class</span><span style="color: blue">&gt;</span>T4Toolbox.XsdProcessor<span style="color: blue">&lt;/</span><span style="color: #a31515">Class</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">CodeBase</span><span style="color: blue">&gt;</span>C:\Program Files (x86)\T4 Toolbox\Bin\T4Toolbox.10.0.dll<span style="color: blue">&lt;/</span><span style="color: #a31515">CodeBase</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">DirectiveProcessor</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">ItemGroup</span><span style="color: blue">&gt;
</span></pre>
<p>Assembly location can be specified using either <em>CodeBase</em> or <em>Assembly</em> metadata item which allows you to reference the assembly from disk or from global assembly cache respectively.</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">ItemGroup</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">DirectiveProcessor </span><span style="color: red">Include</span><span style="color: blue">=</span>&quot;<span style="color: blue">T4Toolbox.XsdProcessor</span>&quot; <span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">Class</span><span style="color: blue">&gt;</span>T4Toolbox.XsdProcessor<span style="color: blue">&lt;/</span><span style="color: #a31515">Class</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">Assembly</span><span style="color: blue">&gt;</span>T4Toolbox.10.0, Version=10.3.7.1, Culture=neutral, PublicKeyToken=7e313accbcce84dc<span style="color: blue">&lt;/</span><span style="color: #a31515">Assembly</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">DirectiveProcessor</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">ItemGroup</span><span style="color: blue">&gt;
</span></pre>
<p><em>@(DirectiveProcessor)</em> items are an equivalent of the –db option of the <a href="http://msdn.microsoft.com/en-us/library/bb126245.aspx">command-line host</a> and the HKLM\Software\Microsoft\VisualStudio\10.0\TextTemplating\DirectiveProcessors registry setting of the Visual Studio host of T4. </p>
<h5 id="T4ParameterValues">@(T4ParameterValues) items</h5>
<p>Specify parameters that custom directive processors and templates themselves can query using <a href="http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.texttemplating.itexttemplatingenginehost.resolveparametervalue.aspx">ResolveParameterValue</a> method. This item list is empty by default.</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">ItemGroup</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">T4ParameterValues </span><span style="color: red">Include</span><span style="color: blue">=</span>&quot;<span style="color: blue">ParameterName</span>&quot;<span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">Value</span><span style="color: blue">&gt;</span>ParameterValue<span style="color: blue">&lt;/</span><span style="color: #a31515">Value</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">T4ParameterValues</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">ItemGroup</span><span style="color: blue">&gt;</span></pre>
<p><em>@(T4ParameterValues)</em> items are an equivalent of the –a option of the <a href="http://msdn.microsoft.com/en-us/library/bb126245.aspx">command-line host</a> and have no direct equivalent in the Visual Studio host of T4.</p>
<h5 id="OutputFilePath">.OutputFilePath metadata</h5>
<p>Specifies the directory where template’s output file will be generated. This metadata item is empty by default.</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">ItemGroup</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">None </span><span style="color: red">Include</span><span style="color: blue">=</span>&quot;<span style="color: blue">Template.tt</span>&quot;<span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">Generator</span><span style="color: blue">&gt;</span>TextTemplatingFileGenerator<span style="color: blue">&lt;/</span><span style="color: #a31515">Generator</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">OutputFilePath</span><span style="color: blue">&gt;</span>$(IntermediateOutputPath)<span style="color: blue">&lt;/</span><span style="color: #a31515">OutputFilePath</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">LastGenOutput</span><span style="color: blue">&gt;</span>Template.cs<span style="color: blue">&lt;/</span><span style="color: #a31515">LastGenOutput</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">None</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">ItemGroup</span><span style="color: blue">&gt;</span></pre>
<p>By default, T4 will place generated output file in the same directory with the template file. You can set this property to redirect generated output files to a different directory during build-time code generation. This property has no effect on design-time code generation performed by the <em>TextTemplatingFileGenerator</em> or <em>TextTemplatingFilePreprocessor</em> when the template file is saved in Visual Studio editor. Setting this property will result in different behavior in code generation at design time vs. build time.</p>
<p><em>.OutputFilePath</em> metadata is an equivalent of the –out option of the <a href="http://msdn.microsoft.com/en-us/library/bb126245.aspx">command-line host</a> and has no direct equivalent in the Visual Studio host of T4.</p>
<p><font color="#ff0000"></font></p>
<h5 id="OutputFileName">.OutputFileName metadata</h5>
<p>Specifies the name of the generated output file. This metadata item is empty by default.</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">ItemGroup</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">None </span><span style="color: red">Include</span><span style="color: blue">=</span>&quot;<span style="color: blue">Template.tt</span>&quot;<span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">Generator</span><span style="color: blue">&gt;</span>TextTemplatingFileGenerator<span style="color: blue">&lt;/</span><span style="color: #a31515">Generator</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">OutputFileName</span><span style="color: blue">&gt;</span>Generated.cs<span style="color: blue">&lt;/</span><span style="color: #a31515">OutputFileName</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">LastGenOutput</span><span style="color: blue">&gt;</span>Template.cs<span style="color: blue">&lt;/</span><span style="color: #a31515">LastGenOutput</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">None</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">ItemGroup</span><span style="color: blue">&gt;</span></pre>
<p>By default, T4 will name generated output file with the name of the template file and the extension specified in the <a href="http://www.olegsych.com/2008/02/t4-output-directive/" target="_blank">output directive</a> in the template. You can set this property to change the default file name during build-time code generation. This property has no effect on design-time code generation performed by the <em>TextTemplatingFileGenerator</em> or <em>TextTemplatingFilePreprocessor</em> when the template file is saved in Visual Studio editor. Setting this property will result in different behavior in code generation at design time vs. build time.</p>
<p><em>.OutputFileName</em> metadata is an equivalent of the –out option of the <a href="http://msdn.microsoft.com/en-us/library/bb126245.aspx">command-line host</a> and has no direct equivalent in the Visual Studio host of T4.</p>
<h5 id="InludeDslT4Settings">$(IncludeDslT4Settings) property</h5>
<p>Determines whether DSL-specific settings should be turned on. This property can be set to true or false and has a default value of false.</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">PropertyGroup</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">IncludeDslT4Settings</span><span style="color: blue">&gt;</span>true<span style="color: blue">&lt;/</span><span style="color: #a31515">IncludeDslT4Settings</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">PropertyGroup</span><span style="color: blue">&gt;</span></pre>
<p>This is a convenience property that configures various settings required for performing build-time template transformation in DSL projects.</p>
<h4 id="ControllingTransformationProcess">Controlling transformation process</h4>
<p>This section lists the various configuration settings that can be used to control the T4 template transformation process in MSBuild project files.</p>
<h5 id="TransformOnBuild">$(TransformOnBuild) property</h5>
<p>Determines whether templates will be transformed at build-time automatically. This property can be set to true or false and has a default value of false. When <em>$(TransformOnBuild)</em> is false, templates will be transformed at design-time in Visual Studio and can also be transformed by <a href="#CallingMSBuildExplicitly">calling MSBuild explicitly</a>.</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">PropertyGroup</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">TransformOnBuild</span><span style="color: blue">&gt;</span>true<span style="color: blue">&lt;/</span><span style="color: #a31515">TransformOnBuild</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">PropertyGroup</span><span style="color: blue">&gt;</span></pre>
<h5 id="TransformOutOfDateOnly">$(TransformOutOfDateOnly) property</h5>
<p>Controls incremental template transformation and indicates whether only out of date or all templates should be processed. This property can be set to true or false and has a default value of true.</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">PropertyGroup</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">TransformOutOfDateOnly</span><span style="color: blue">&gt;</span>false<span style="color: blue">&lt;/</span><span style="color: #a31515">TransformOutOfDateOnly</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">PropertyGroup</span><span style="color: blue">&gt;</span></pre>
<p>An out-of-date file is one where any of the input files used to generated the file were modified more recently than the file itself. The input files are the <a href="http://www.olegsych.com/2008/02/t4-include-directive/" target="_blank">included</a> template files and the files referenced by custom directive processors. In addition, a file that contains only “ErrorGeneratingOutput” written to it when the last transformation failed is also treated as being out of date. </p>
<p>T4 relies on the file tracking feature in MSBuild by logging all of the file read / write operations as they occur when generating an output file. If the tracking logs do not exist for a project, T4 assumes that the template is out of date and transforms it.</p>
<h5 id="TrackFileAccess">$(TrackFileAccess) property</h5>
<p>Determines whether T4 will log file read / write operations to allow subsequent incremental template transformations. This property can be set to true or false and has a default value of true.</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">PropertyGroup</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">TrackFileAccess</span><span style="color: blue">&gt;</span>false<span style="color: blue">&lt;/</span><span style="color: #a31515">TrackFileAccess</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">PropertyGroup</span><span style="color: blue">&gt;</span></pre>
<p>If you don’t rely on incremental template transformations, you may want to set this property to false to reduce the amount of space taken by the log files in the intermediate output directory (obj\Debug).</p>
<h5 id="OverwriteReadOnlyOutputFiles">$(OverwriteReadOnlyOutputFiles) property</h5>
<p>Indicates whether read-only output files will be overwritten during template transformation. This property can be set to true or false and has a default value of false.</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">PropertyGroup</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">OverwriteReadOnlyOutputFiles</span><span style="color: blue">&gt;</span>true<span style="color: blue">&lt;/</span><span style="color: #a31515">OverwriteReadOnlyOutputFiles</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">PropertyGroup</span><span style="color: blue">&gt;</span></pre>
<p>When <em>$(OverwriteReadOnlyOutputFiles)</em> is false, T4 issues a warning for each output file that could not be regenerated because it is read-only and the build will fail. When <em>$(OverwriteReadOnlyOutputFiles)</em> is true, T4 will overwrite read-only files and report a warning for each overwritten file. These warnings are not considered to be compiler warnings for the purpose of the “Treat warnings as errors” project setting.</p>
<h5 id="BeforeTransform">$(BeforeTransform) property</h5>
<p>Specifies a user-defined MSBuild target that will be executed before template transformation. This property is empty by default.</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">PropertyGroup</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">TransformOnBuild</span><span style="color: blue">&gt;</span>true<span style="color: blue">&lt;/</span><span style="color: #a31515">TransformOnBuild</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">BeforeTransform</span><span style="color: blue">&gt;</span>OnBeforeTransform<span style="color: blue">&lt;/</span><span style="color: #a31515">BeforeTransform</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">PropertyGroup</span><span style="color: blue">&gt;
&lt;</span><span style="color: #a31515">Import </span><span style="color: red">Project</span><span style="color: blue">=</span>&quot;<span style="color: blue">$(MSBuildExtensionsPath)\Microsoft\VisualStudio\TextTemplating\v10.0\Microsoft.TextTemplating.targets</span>&quot; <span style="color: blue">/&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">OnBeforeTransform</span>&quot;<span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">Message </span><span style="color: red">Text</span><span style="color: blue">=</span>&quot;<span style="color: blue">This executes before templates are transformed</span>&quot; <span style="color: red">Importance</span><span style="color: blue">=</span>&quot;<span style="color: blue">high</span>&quot;<span style="color: blue">/&gt;
&lt;/</span><span style="color: #a31515">Target</span><span style="color: blue">&gt;
</span></pre>
<h5 id="AfterTransform">$(AfterTransform) property</h5>
<p>Specifies a user-defined MSBuild target that will be executed before template transformation. This property is empty by default.</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">PropertyGroup</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">TransformOnBuild</span><span style="color: blue">&gt;</span>true<span style="color: blue">&lt;/</span><span style="color: #a31515">TransformOnBuild</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">AfterTransform</span><span style="color: blue">&gt;</span>OnAfterTransform<span style="color: blue">&lt;/</span><span style="color: #a31515">AfterTransform</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">PropertyGroup</span><span style="color: blue">&gt;
&lt;</span><span style="color: #a31515">Import </span><span style="color: red">Project</span><span style="color: blue">=</span>&quot;<span style="color: blue">$(MSBuildExtensionsPath)\Microsoft\VisualStudio\TextTemplating\v10.0\Microsoft.TextTemplating.targets</span>&quot; <span style="color: blue">/&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">OnAfterTransform</span>&quot;<span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">Message </span><span style="color: red">Text</span><span style="color: blue">=</span>&quot;<span style="color: blue">This executes after templates are transformed</span>&quot; <span style="color: red">Importance</span><span style="color: blue">=</span>&quot;<span style="color: blue">high</span>&quot;<span style="color: blue">/&gt;
&lt;/</span><span style="color: #a31515">Target</span><span style="color: blue">&gt;
</span></pre>
<h5 id="GeneratedFiles">@(GeneratedFiles) items</h5>
<p>Are produced by by the <em>TransformTemplates </em>and <em>PreprocessTemplates</em> to indicate output files that were successfully generated. <em>@(GeneratedFiles)</em> have <em>.ReadOnlyFileOverwritten</em> metadata item set to true when <em>$(OverwriteReadOnlyOutputFiles)</em> property is set to true and a particular read-only output file was overwritten during code generation. <em>@(GeneratedFiles)</em> items can be used in the user-defined <em>AfterTransform</em> target.</p>
<h5 id="NonGeneratedFiles">@(NonGeneratedFiles) items</h5>
<p>Are produced by by the <em>TransformTemplates </em>and <em>PreprocessTemplates</em> to indicate output files that could not be regenerated. The list of <em>@(NonGeneratedFiles)</em> can be examined in the user-defined <em>AfterTransform</em> target.</p>
<h4 id="CallingMSBuildExplicitly">Transforming templates by calling MSBuild explicitly</h4>
<p>In addition to automatically transforming templates at build time, T4 provides two targets you can call explicitly to transform or preprocess templates in a particular project by invoking MSBuild from command line. </p>
<h5 id="TransformAll">TransformAll target</h5>
<p>Calling the TransformAll target will transform all files associated with <em>TextTemplatingFileGenerator</em> and <em>TextTemplatingFilePreprocessor</em> in the specified project. It is an equivalent of setting <em>$(TransformOnBuild)</em> to true and performing template transformation at build time.</p>
<h6>Syntax</h6>
<pre class="code">msbuild t4msbuild.csproj /t:TransformAll</pre>
<h6>Sample Output</h6>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image_thumb14[3]" border="0" alt="image_thumb14[3]" src="http://www.olegsych.com/wp-content/uploads/2010/04/image-thumb143.png" width="580" height="401" /> </p>
</p>
<h5 id="Transform">Transform target</h5>
<p>Transform target allows you to specify which file or files have to be transformed. It expects you to provide a value for <em>TransformFile</em> property, which accepts individual file names as well as <a href="http://msdn.microsoft.com/en-us/library/ms171454.aspx" target="_blank">MSBuild wildcards</a>.</p>
<h6>Syntax</h6>
<pre class="code">msbuild t4msbuild.csproj /t:Transform /p:TransformFile=*.tt</pre>
<h6>Sample Output</h6>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="" border="0" alt="" src="http://www.olegsych.com/wp-content/uploads/2010/04/image-thumb133.png" width="580" height="401" /> </p>
<h4 id="Conclusion">Conclusion</h4>
<p>Visual Studio 2010 introduced a new capability based on MSBuild extensions for transforming and preprocessing text templates at build time. The new capability comes with a set of distinct advantages and drawbacks. Compared to the existing command line tool, <em>TextTransform</em>, it makes implementation and maintenance of build-time template transformation easier. However, compared to the existing Visual Studio tools, it does not support project and source control integration. The MSBuild extensions also rely on a brand-new T4 engine host, with a unique compilation and run-time environment for text templates. Templates that take advantage of specific capabilities provided by a particular host (such as ASP.NET MVC and T4 Toolbox templates) are not be compatible with the new MSBuild host. Templates designed to be host-agnostic, may require you to configure the MSBuild host before they can be processed correctly. In particular, locations of the included files, .NET assemblies and definitions of custom directive processors have to be supplied explicitly. </p>
<h4 id="Download">Download</h4>
<ul>
<li><a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=47305cf4-2bea-43c0-91cd-1b853602dcc5" target="_blank">Visual Studio 2010 SDK</a> (pre-requisite) </li>
<li><a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=0def949d-2933-49c3-ac50-e884e0ff08a7" target="_blank">Visual Studio 2010 Modeling and Visualization SDK</a> (pre-requisite) </li>
</ul>
<p>&copy;2012 <a href="http://www.olegsych.com">Oleg Sych</a>. All Rights Reserved.</p>.<img src="http://feeds.feedburner.com/~r/olegsych/~4/IUhVB03HcQA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.olegsych.com/2010/04/understanding-t4-msbuild-integration/feed/</wfw:commentRss>
		</item>
		<item>
		<title>T4 Tutorial: Integrating Generated Files in Visual Studio Projects</title>
		<link>http://www.olegsych.com/2010/03/t4-tutorial-integrating-generated-files-in-visual-studio-projects/</link>
		<comments>http://www.olegsych.com/2010/03/t4-tutorial-integrating-generated-files-in-visual-studio-projects/#comments</comments>
		<pubDate>Sat, 13 Mar 2010 23:51:48 +0000</pubDate>
		<dc:creator>Oleg Sych</dc:creator>
		
		<category><![CDATA[Articles]]></category>

		<guid isPermaLink="false">http://www.olegsych.com/2010/03/t4-tutorial-integrating-generated-files-in-visual-studio-projects/</guid>
		<description><![CDATA[This post is a part of the series that introduces code generation with Text Templates (also known as T4 Templates) in Visual Studio using C# and Visual Basic; 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 [...]]]></description>
			<content:encoded><![CDATA[<p>This post is a part of the series that introduces code generation with <a href="http://msdn.microsoft.com/en-us/library/bb126445.aspx">Text Templates</a> (also known as <a href="http://www.olegsych.com/2007/12/text-template-transformation-toolkit/">T4</a> Templates) in Visual Studio using C# and Visual Basic; 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 SP1 or later, <a href="http://t4toolbox.codeplex.com">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>Output Integration Capabilities of T4 Toolbox</h4>
<p><a href="http://t4toolbox.codeplex.com" target="_blank">T4 Toolbox</a> offers rich capabilities for integrating generated output files in Visual Studio projects, including automatically adding generated files to multiple projects, specifying project item attributes, adding assembly references to target projects and more. The framework allows specifying these integration details declaratively, takes care of the plumbing and helps developers to concentrate on the code generation itself. </p>
<p>Integration capabilities are exposed through the <em>Output</em> property of <em>Template</em> class in T4 Toolbox. As you remember, Template class represents a single logical unit of code generation. For example, you might create a template that generates a single .NET class or a SQL stored procedure. Here is what it might look like.</p>
<h6>C#</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffd700; color: #000000">&lt;#+</span><span style="background-color: #ffffff; color: #000000">
</span><span style="background-color: #ffffe0; color: #0000ff">public</span><span style="background-color: #ffffe0; color: #000000"> </span><span style="background-color: #ffffe0; color: #0000ff">class</span><span style="background-color: #ffffe0; color: #000000"> TableTemplate : Template
{
    </span><span style="background-color: #ffffe0; color: #0000ff">public</span><span style="background-color: #ffffe0; color: #000000"> </span><span style="background-color: #ffffe0; color: #0000ff">override</span><span style="background-color: #ffffe0; color: #000000"> </span><span style="background-color: #ffffe0; color: #0000ff">string</span><span style="background-color: #ffffe0; color: #000000"> TransformText()
    {
</span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="color: #0000ff">CREATE</span><span style="color: #000000"> </span><span style="color: #0000ff">TABLE</span><span style="color: #000000"> </span><span style="color: #ff0000">[</span><span style="color: #ff0000">dbo</span><span style="color: #ff0000">]</span><span style="color: #000000">.</span><span style="color: #ff0000">[</span><span style="color: #ff0000">TableCs</span><span style="color: #ff0000">]</span><span style="color: #000000">
(
    column_1 </span><span style="color: #0000ff">int</span><span style="color: #000000"> </span><span style="color: #808080">NOT</span><span style="color: #000000"> </span><span style="color: #0000ff">NULL</span><span style="color: #000000">,
    column_2 </span><span style="color: #0000ff">int</span><span style="color: #000000"> </span><span style="color: #0000ff">NULL</span><span style="color: #000000">
)
</span><span style="background-color: #ffd700; color: #000000">&lt;#+</span><span style="background-color: #ffffe0; color: #0000ff">
        return</span><span style="background-color: #ffffe0; color: #000000"> </span><span style="background-color: #ffffe0; color: #0000ff">this</span><span style="background-color: #ffffe0; color: #000000">.GenerationEnvironment.ToString();
    }
}
</span><span style="background-color: #ffd700; color: #000000">#&gt;</span></pre>
<h6>VB</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffd700; color: #000000">&lt;#+</span><span style="background-color: #ffffe0; color: #000000">
</span><span style="background-color: #ffffe0; color: #0000ff">Public</span><span style="background-color: #ffffe0; color: #000000"> </span><span style="background-color: #ffffe0; color: #0000ff">Class</span><span style="background-color: #ffffe0; color: #000000"> TableTemplate
    </span><span style="background-color: #ffffe0; color: #0000ff">Inherits</span><span style="background-color: #ffffe0; color: #000000"> Template

    </span><span style="background-color: #ffffe0; color: #0000ff">Public</span><span style="background-color: #ffffe0; color: #000000"> </span><span style="background-color: #ffffe0; color: #0000ff">Overrides</span><span style="background-color: #ffffe0; color: #000000"> </span><span style="background-color: #ffffe0; color: #0000ff">Function</span><span style="background-color: #ffffe0; color: #000000"> TransformText() </span><span style="background-color: #ffffe0; color: #0000ff">As</span><span style="background-color: #ffffe0; color: #000000"> </span><span style="background-color: #ffffe0; color: #0000ff">String</span><span style="background-color: #ffffff; color: #000000">
</span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="color: #0000ff">CREATE</span><span style="color: #000000"> </span><span style="color: #0000ff">TABLE</span><span style="color: #000000"> </span><span style="color: #ff0000">[</span><span style="color: #ff0000">dbo</span><span style="color: #ff0000">]</span><span style="color: #000000">.</span><span style="color: #ff0000">[</span><span style="color: #ff0000">TableVb</span><span style="color: #ff0000">]</span><span style="color: #000000">
(
    column_1 </span><span style="color: #0000ff">int</span><span style="color: #000000"> </span><span style="color: #808080">NOT</span><span style="color: #000000"> </span><span style="color: #0000ff">NULL</span><span style="color: #000000">,
    column_2 </span><span style="color: #0000ff">int</span><span style="color: #000000"> </span><span style="color: #0000ff">NULL</span><span style="color: #000000">
)
</span><span style="background-color: #ffd700; color: #000000">&lt;#+</span><span style="background-color: #ffffe0; color: #0000ff">
        Return</span><span style="background-color: #ffffe0; color: #000000"> </span><span style="background-color: #ffffe0; color: #0000ff">Me</span><span style="background-color: #ffffe0; color: #000000">.GenerationEnvironment.ToString()
    </span><span style="background-color: #ffffe0; color: #0000ff">End</span><span style="background-color: #ffffe0; color: #000000"> </span><span style="background-color: #ffffe0; color: #0000ff">Function</span><span style="background-color: #ffffff; color: #000000">

</span><span style="background-color: #ffffe0; color: #0000ff">End</span><span style="background-color: #ffffe0; color: #000000"> </span><span style="background-color: #ffffe0; color: #0000ff">Class</span><span style="background-color: #ffffff; color: #000000">
</span><span style="background-color: #ffd700; color: #000000">#&gt;</span></pre>
<p>Having defined the template, we can use it to generate code like so.</p>
<h6>C#</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">template</span><span style="color: #000000"> </span><span style="color: #ff0000">language</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">C#</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="color: #ff0000">hostspecific</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">True</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="color: #ff0000">debug</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">True</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">output</span><span style="color: #000000"> </span><span style="color: #ff0000">extension</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">sql</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">include</span><span style="color: #000000"> </span><span style="color: #ff0000">file</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">T4Toolbox.tt</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">include</span><span style="color: #000000"> </span><span style="color: #ff0000">file</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">TableTemplate.tt</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#</span><span style="background-color: #ffffe0; color: #000000">
    TableTemplate t = </span><span style="background-color: #ffffe0; color: #0000ff">new</span><span style="background-color: #ffffe0; color: #000000"> TableTemplate();
    t.Render();
</span><span style="background-color: #ffd700; color: #000000">#&gt;</span></pre>
<h6>VB</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">template</span><span style="color: #000000"> </span><span style="color: #ff0000">language</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">VB</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="color: #ff0000">hostspecific</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">True</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="color: #ff0000">debug</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">True</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">output</span><span style="color: #000000"> </span><span style="color: #ff0000">extension</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">sql</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">include</span><span style="color: #000000"> </span><span style="color: #ff0000">file</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">T4Toolbox.tt</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">include</span><span style="color: #000000"> </span><span style="color: #ff0000">file</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">TableTemplate.tt</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#</span><span style="background-color: #ffffe0; color: #000000">
    </span><span style="background-color: #ffffe0; color: #0000ff">Dim</span><span style="background-color: #ffffe0; color: #000000"> t </span><span style="background-color: #ffffe0; color: #0000ff">as</span><span style="background-color: #ffffe0; color: #000000"> TableTemplate = </span><span style="background-color: #ffffe0; color: #0000ff">New</span><span style="background-color: #ffffe0; color: #000000"> TableTemplate()
    t.Render()
</span><span style="background-color: #ffd700; color: #000000">#&gt;</span></pre>
<h6>Output</h6>
<pre class="code"><span style="color: blue">CREATE TABLE </span>[dbo].[TableCs]
(
    column_1 <span style="color: blue">int NOT NULL</span>,
    column_2 <span style="color: blue">int NULL
</span>)</pre>
<p><em>Template.Output </em>property returns an instance of <em><u>OutputInfo</u></em> class which you can use to declaratively specify how output generated by the template will be integrated by the T4 Toolbox framework.</p>
<h5><img style="border-bottom: 0px; border-left: 0px; margin: 0px 0px 0px 5px; display: inline; border-top: 0px; border-right: 0px" title="" border="0" alt="" align="right" src="http://www.olegsych.com/wp-content/uploads/2010/03/image26.png" width="160" height="156" /></h5>
<h4>Output.File property</h4>
<p><em>File</em> property of the <em>OutputInfo </em>class specifies name of the file where generated output will be saved. By default, it is empty, meaning that generated output will be added to the standard output file generated for the root .tt file by Visual Studio. Here is an example of setting this property to save generated output in a separate file. </p>
<h6>C#</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffd700; color: #000000">&lt;#</span><span style="background-color: #ffffe0; color: #000000">
  TableTemplate t = </span><span style="background-color: #ffffe0; color: #0000ff">new</span><span style="background-color: #ffffe0; color: #000000"> TableTemplate();
  t.Output.File = </span><span style="background-color: #ffffe0; color: #800000">&quot;Table.sql&quot;</span><span style="background-color: #ffffe0; color: #000000">;
  t.Render();
</span><span style="background-color: #ffd700; color: #000000">#&gt;</span></pre>
<h6>VB</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffd700; color: #000000">&lt;#</span><span style="background-color: #ffffe0; color: #000000">
    </span><span style="background-color: #ffffe0; color: #0000ff">Dim</span><span style="background-color: #ffffe0; color: #000000"> t </span><span style="background-color: #ffffe0; color: #0000ff">as</span><span style="background-color: #ffffe0; color: #000000"> TableTemplate = </span><span style="background-color: #ffffe0; color: #0000ff">New</span><span style="background-color: #ffffe0; color: #000000"> TableTemplate()
    t.Output.File = </span><span style="background-color: #ffffe0; color: #800000">&quot;Table.sql&quot;</span><span style="background-color: #ffffe0; color: #000000">
    t.Render()
</span><span style="background-color: #ffd700; color: #000000">#&gt;</span></pre>
<p><img style="border-bottom: 0px; border-left: 0px; margin: 0px 0px 0px 5px; display: inline; border-top: 0px; border-right: 0px" title="" border="0" alt="" align="right" src="http://www.olegsych.com/wp-content/uploads/2010/03/image27.png" width="160" height="169" /><em>Output.File</em> property value can also include file path. When it does, T4 Toolbox will save the file in the specified folder. When the generated file is not located in the same folder with the root .tt template, T4 Toolbox will also create a code generation log file (<em>Script.tt.log </em>in this example) for keeping track of the generated file, which is now stored away from the root .tt file. T4 Toolbox keeps track of all generated files in order to automatically remove them when they are no longer regenerated. </p>
<h6>C#</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffd700; color: #000000">&lt;#</span><span style="background-color: #ffffe0; color: #000000">
  TableTemplate t = </span><span style="background-color: #ffffe0; color: #0000ff">new</span><span style="background-color: #ffffe0; color: #000000"> TableTemplate();
  t.Output.File = </span><span style="background-color: #ffffe0; color: #800000">@&quot;SQL Scripts\Table.sql&quot;</span><span style="background-color: #ffffe0; color: #000000">;
  t.Render();
</span><span style="background-color: #ffd700; color: #000000">#&gt;</span></pre>
<h6>VB</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffd700; color: #000000">&lt;#</span><span style="background-color: #ffffe0; color: #000000">
    </span><span style="background-color: #ffffe0; color: #0000ff">Dim</span><span style="background-color: #ffffe0; color: #000000"> t </span><span style="background-color: #ffffe0; color: #0000ff">as</span><span style="background-color: #ffffe0; color: #000000"> TableTemplate = </span><span style="background-color: #ffffe0; color: #0000ff">New</span><span style="background-color: #ffffe0; color: #000000"> TableTemplate()
    t.Output.File = </span><span style="background-color: #ffffe0; color: #800000">&quot;SQL Scripts\Table.sql&quot;</span><span style="background-color: #ffffe0; color: #000000">
    t.Render()
</span><span style="background-color: #ffd700; color: #000000">#&gt;</span></pre>
<p><a href="http://www.olegsych.com/wp-content/uploads/2010/03/image28.png"><img style="border-bottom: 0px; border-left: 0px; margin: 0px; display: inline; border-top: 0px; border-right: 0px" title="" border="0" alt="" align="right" src="http://www.olegsych.com/wp-content/uploads/2010/03/image-thumb8.png" width="170" height="142" /></a>Output of multiple templates can be combined in a single file. When the <em>File</em> property is empty for multiple templates, their outputs are combined in the standard output file of the root .tt file. Similarly, when the <em>File </em>property of several templates is set to the same file name, their outputs will be combined in the specified, separate file. This capability allows you to design a code generator to be granular by default, but allow combining the outputs when managing a single generated file is desired. The following example illustrates a code generator that combines generated table and stored procedure in a single SQL script.</p>
<h6>C#</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffd700; color: #000000">&lt;#</span><span style="background-color: #ffffe0; color: #000000">
  </span><span style="background-color: #ffffe0; color: #0000ff">var</span><span style="background-color: #ffffe0; color: #000000"> t = </span><span style="background-color: #ffffe0; color: #0000ff">new</span><span style="background-color: #ffffe0; color: #000000"> TableTemplate();
  t.Output.File = </span><span style="background-color: #ffffe0; color: #800000">&quot;Database.sql&quot;</span><span style="background-color: #ffffe0; color: #000000">;
  t.Render();

  </span><span style="background-color: #ffffe0; color: #0000ff">var</span><span style="background-color: #ffffe0; color: #000000"> p = </span><span style="background-color: #ffffe0; color: #0000ff">new</span><span style="background-color: #ffffe0; color: #000000"> ProcedureTemplate();
  p.Output.File = </span><span style="background-color: #ffffe0; color: #800000">&quot;Database.sql&quot;</span><span style="background-color: #ffffe0; color: #000000">;
  p.Render();
</span><span style="background-color: #ffd700; color: #000000">#&gt;</span></pre>
<h6>VB</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffd700; color: #000000">&lt;#</span><span style="background-color: #ffffe0; color: #000000">
  </span><span style="background-color: #ffffe0; color: #0000ff">Dim</span><span style="background-color: #ffffe0; color: #000000"> t </span><span style="background-color: #ffffe0; color: #0000ff">as</span><span style="background-color: #ffffe0; color: #000000"> </span><span style="background-color: #ffffe0; color: #0000ff">New</span><span style="background-color: #ffffe0; color: #000000"> TableTemplate()
  t.Output.File = </span><span style="background-color: #ffffe0; color: #800000">&quot;Database.sql&quot;</span><span style="background-color: #ffffe0; color: #000000">
  t.Render()

  </span><span style="background-color: #ffffe0; color: #0000ff">Dim</span><span style="background-color: #ffffe0; color: #000000"> p </span><span style="background-color: #ffffe0; color: #0000ff">as</span><span style="background-color: #ffffe0; color: #000000"> </span><span style="background-color: #ffffe0; color: #0000ff">New</span><span style="background-color: #ffffe0; color: #000000"> ProcedureTemplate()
  p.Output.File = </span><span style="background-color: #ffffe0; color: #800000">&quot;Database.sql&quot;</span><span style="background-color: #ffffe0; color: #000000">
  p.Render()
</span><span style="background-color: #ffd700; color: #000000">#&gt;</span></pre>
<h6>Output</h6>
<pre class="code"><span style="color: blue">CREATE TABLE </span>[dbo].[TableCs]
(
    column_1 <span style="color: blue">int NOT NULL</span>,
    column_2 <span style="color: blue">int NULL
</span>);
<span style="color: blue">CREATE PROCEDURE </span>[dbo].[ProcedureCs]
    @param1 <span style="color: blue">int </span>= 0,
    @param2 <span style="color: blue">int
AS
    SELECT </span>@param1, @param2
<span style="color: blue">RETURN </span>0;</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<h4>Output.Encoding property</h4>
<p><em>Encoding</em> property of the <em>OutputInfo </em>class specifies the <a href="http://msdn.microsoft.com/en-us/library/system.text.encoding.aspx" target="_blank">Encoding</a> that will be used to save the output file. This property is an equivalent of the <em>encoding</em> attribute in the standard <a href="http://www.olegsych.com/2008/02/t4-output-directive/">output directive</a> in T4. It is set to ANSI by default. One of examples of when you may want to explicitly specify encoding of the output file is when your template generates XML and specifies encoding in the file content, which needs to match.</p>
<h6>C#</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">import</span><span style="color: #000000"> </span><span style="color: #ff0000">namespace</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">System.Text</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#</span><span style="background-color: #ffffe0; color: #000000">
  </span><span style="background-color: #ffffe0; color: #0000ff">var</span><span style="background-color: #ffffe0; color: #000000"> t = </span><span style="background-color: #ffffe0; color: #0000ff">new</span><span style="background-color: #ffffe0; color: #000000"> XmlTemplate();
  t.Output.File = </span><span style="background-color: #ffffe0; color: #800000">&quot;File.xml&quot;</span><span style="background-color: #ffffe0; color: #000000">;
  t.Output.Encoding = Encoding.UTF8;
  t.Render();
</span><span style="background-color: #ffd700; color: #000000">#&gt;</span></pre>
<h6>VB</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">import</span><span style="color: #000000"> </span><span style="color: #ff0000">namespace</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">System.Text</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#</span><span style="background-color: #ffffe0; color: #000000">
  </span><span style="background-color: #ffffe0; color: #0000ff">Dim</span><span style="background-color: #ffffe0; color: #000000"> t </span><span style="background-color: #ffffe0; color: #0000ff">as</span><span style="background-color: #ffffe0; color: #000000"> </span><span style="background-color: #ffffe0; color: #0000ff">New</span><span style="background-color: #ffffe0; color: #000000"> XmlTemplate()
  t.Output.File = </span><span style="background-color: #ffffe0; color: #800000">&quot;File.xml&quot;</span><span style="background-color: #ffffe0; color: #000000">
  t.Output.Encoding = Encoding.UTF8
  t.Render()
</span><span style="background-color: #ffd700; color: #000000">#&gt;</span></pre>
<h5><a href="http://www.olegsych.com/wp-content/uploads/2010/03/image22.png"><img style="border-bottom: 0px; border-left: 0px; margin: 0px 0px 0px 5px; display: inline; border-top: 0px; border-right: 0px" title="" border="0" alt="" align="right" src="http://www.olegsych.com/wp-content/uploads/2010/03/image-thumb7.png" width="120" height="213" /></a></h5>
<h4>Output.Project property</h4>
<p><em>Project</em> property of the <em>OutputInfo </em>class specifies the project file to which the output file will be added. You will usually set this property to a path relative from the .tt file to the target project file. In addition, you will also typically set the File property to specify name and location of the output file within the target project. There is an important different between the <em>File</em> and <em>Project </em>properties in the way they treat relative paths. <em>Project </em>property always assumes that path is relative to the location of the root .tt file, whereas <em>File </em>property assumes that path is relative to the location of the target project file when the <em>Project </em>property is specified.</p>
<h6>C#</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffd700; color: #000000">&lt;#</span><span style="background-color: #ffffe0; color: #000000">
  TableTemplate t = </span><span style="background-color: #ffffe0; color: #0000ff">new</span><span style="background-color: #ffffe0; color: #000000"> TableTemplate();
  t.Output.Project = </span><span style="background-color: #ffffe0; color: #800000">@&quot;..\Database\Database.dbproj&quot;</span><span style="background-color: #ffffe0; color: #000000">;
  t.Output.File = </span><span style="background-color: #ffffe0; color: #800000">@&quot;Schema Objects\Schemas\dbo\Tables\TableCs.table.sql&quot;</span><span style="background-color: #ffffe0; color: #000000">;
  t.Render();
</span><span style="background-color: #ffd700; color: #000000">#&gt;</span></pre>
<h6>VB</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffd700; color: #000000">&lt;#</span><span style="background-color: #ffffe0; color: #000000">
  </span><span style="background-color: #ffffe0; color: #0000ff">Dim</span><span style="background-color: #ffffe0; color: #000000"> t </span><span style="background-color: #ffffe0; color: #0000ff">as</span><span style="background-color: #ffffe0; color: #000000"> TableTemplate = </span><span style="background-color: #ffffe0; color: #0000ff">New</span><span style="background-color: #ffffe0; color: #000000"> TableTemplate()
  t.Output.Project = </span><span style="background-color: #ffffe0; color: #800000">&quot;..\Database\Database.dbproj&quot;</span><span style="background-color: #ffffe0; color: #000000">
  t.Output.File = </span><span style="background-color: #ffffe0; color: #800000">&quot;Schema Objects\Schemas\dbo\Tables\TableVb.table.sql&quot;</span><span style="background-color: #ffffe0; color: #000000">
  t.Render()
</span><span style="background-color: #ffd700; color: #000000">#&gt;</span></pre>
<h5><img style="border-bottom: 0px; border-left: 0px; margin: 0px 0px 0px 5px; display: inline; border-top: 0px; border-right: 0px" title="" border="0" alt="" align="right" src="http://www.olegsych.com/wp-content/uploads/2010/03/image23.png" width="164" height="157" /></h5>
<h4>Output.BuildAction property</h4>
<p><em>BuildAction</em> property of the <em>OutputInfo </em>class specifies the build action that will be assigned for the output file in the target project. By default, this property is not assigned, allowing Visual Studio to pick the build action appropriate for the file type. Because build actions can be customized by importing MSBuild target files, the type of <em>BuildAction</em> property is not an enumeration, but a string. Common build actions, such as <em>Content</em>, <em>Compile </em>and <em>EmbeddedResource</em> are available as constants in a static class called <em>BuildAction</em>. </p>
<h6>C#</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffd700; color: #000000">&lt;#</span><span style="background-color: #ffffe0; color: #000000">
  TableTemplate t = </span><span style="background-color: #ffffe0; color: #0000ff">new</span><span style="background-color: #ffffe0; color: #000000"> TableTemplate();
  t.Output.File = </span><span style="background-color: #ffffe0; color: #800000">&quot;TableCs.sql&quot;</span><span style="background-color: #ffffe0; color: #000000">;
  t.Output.BuildAction = BuildAction.Content;
  t.Render();
</span><span style="background-color: #ffd700; color: #000000">#&gt;</span></pre>
<h6>VB</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffd700; color: #000000">&lt;#</span><span style="background-color: #ffffe0; color: #000000">
  </span><span style="background-color: #ffffe0; color: #0000ff">Dim</span><span style="background-color: #ffffe0; color: #000000"> t </span><span style="background-color: #ffffe0; color: #0000ff">as</span><span style="background-color: #ffffe0; color: #000000"> TableTemplate = </span><span style="background-color: #ffffe0; color: #0000ff">New</span><span style="background-color: #ffffe0; color: #000000"> TableTemplate()
  t.Output.File = </span><span style="background-color: #ffffe0; color: #800000">&quot;TableVb.sql&quot;</span><span style="background-color: #ffffe0; color: #000000">
  t.Output.BuildAction = BuildAction.Content
  t.Render()
</span><span style="background-color: #ffd700; color: #000000">#&gt;</span></pre>
<h4>Output.CopyToOutputDirectory property</h4>
<p><img style="border-bottom: 0px; border-left: 0px; margin: 0px 0px 0px 5px; display: inline; border-top: 0px; border-right: 0px" title="" border="0" alt="" align="right" src="http://www.olegsych.com/wp-content/uploads/2010/03/image24.png" width="164" height="152" /><em>CopyToOutputDirectory</em> property of the <em>OutputInfo</em> class specifies the value that will be assigned to “Copy to Output Directory” attribute of the output file in the target project. The type of <em>CopyToOutputDirectory</em> property is an enumeration also called <em>CopyToOutputDirectory</em>, with items like <em>CopyAlways</em>, <em>CopyIfNewer</em> and <em>DoNotCopy</em> (default).</p>
<h6>C#</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffd700; color: #000000">&lt;#</span><span style="background-color: #ffffe0; color: #000000">
  TableTemplate t = </span><span style="background-color: #ffffe0; color: #0000ff">new</span><span style="background-color: #ffffe0; color: #000000"> TableTemplate();
  t.Output.File = </span><span style="background-color: #ffffe0; color: #800000">&quot;TableCs.sql&quot;</span><span style="background-color: #ffffe0; color: #000000">;
  t.Output.CopyToOutputDirectory = CopyToOutputDirectory.CopyAlways;
  t.Render();
</span><span style="background-color: #ffd700; color: #000000">#&gt;</span></pre>
<h6>VB</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffd700; color: #000000">&lt;#</span><span style="background-color: #ffffe0; color: #000000">
  </span><span style="background-color: #ffffe0; color: #0000ff">Dim</span><span style="background-color: #ffffe0; color: #000000"> t </span><span style="background-color: #ffffe0; color: #0000ff">as</span><span style="background-color: #ffffe0; color: #000000"> TableTemplate = </span><span style="background-color: #ffffe0; color: #0000ff">New</span><span style="background-color: #ffffe0; color: #000000"> TableTemplate()
  t.Output.File = </span><span style="background-color: #ffffe0; color: #800000">&quot;TableVb.sql&quot;</span><span style="background-color: #ffffe0; color: #000000">
  t.Output.CopyToOutputDirectory = CopyToOutputDirectory.CopyAlways
  t.Render()
</span><span style="background-color: #ffd700; color: #000000">#&gt;</span></pre>
<h4>Output.CustomTool and Output.CustomToolNamespace properties</h4>
<p><img style="border-bottom: 0px; border-left: 0px; margin: 0px 0px 0px 5px; display: inline; border-top: 0px; border-right: 0px" title="" border="0" alt="" align="right" src="http://www.olegsych.com/wp-content/uploads/2010/03/image25.png" width="184" height="156" /><em>CustomTool</em> and <em>CustomToolNamespace </em>properties of the <em>OutputInfo</em> class specify the value that will be assigned to the “Custom Tool” and “Custom Tool Namespace” attributes of the output file. These properties are of type string. They are null by default, which leaves Visual Studio to pick appropriate defaults based the file type. The following example illustrates generating a resource file, assigning ResXFileCodeGenerator to automatically generate a strongly-typed .NET wrapper for the resource in a particular namespace.</p>
<h6>C#</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffd700; color: #000000">&lt;#</span><span style="background-color: #ffffe0; color: #000000">
  </span><span style="background-color: #ffffe0; color: #0000ff">var</span><span style="background-color: #ffffe0; color: #000000"> t = </span><span style="background-color: #ffffe0; color: #0000ff">new</span><span style="background-color: #ffffe0; color: #000000"> ResourceTemplate();
  t.Output.File = </span><span style="background-color: #ffffe0; color: #800000">&quot;Resource.resx&quot;</span><span style="background-color: #ffffe0; color: #000000">;
  t.Output.CustomTool = </span><span style="background-color: #ffffe0; color: #800000">&quot;ResXFileCodeGenerator&quot;</span><span style="background-color: #ffffe0; color: #000000">;
  t.Output.CustomToolNamespace = </span><span style="background-color: #ffffe0; color: #800000">&quot;CustomNamespace&quot;</span><span style="background-color: #ffffe0; color: #000000">;
  t.Render();
</span><span style="background-color: #ffd700; color: #000000">#&gt;</span></pre>
<h6>VB</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffd700; color: #000000">&lt;#</span><span style="background-color: #ffffe0; color: #000000">
  </span><span style="background-color: #ffffe0; color: #0000ff">Dim</span><span style="background-color: #ffffe0; color: #000000"> t </span><span style="background-color: #ffffe0; color: #0000ff">as</span><span style="background-color: #ffffe0; color: #000000"> </span><span style="background-color: #ffffe0; color: #0000ff">New</span><span style="background-color: #ffffe0; color: #000000"> ResourceTemplate()
  t.Output.File = </span><span style="background-color: #ffffe0; color: #800000">&quot;Resource.resx&quot;</span><span style="background-color: #ffffe0; color: #000000">
  t.Output.CustomTool = </span><span style="background-color: #ffffe0; color: #800000">&quot;ResXFileCodeGenerator&quot;</span><span style="background-color: #ffffe0; color: #000000">
  t.Output.CustomToolNamespace = </span><span style="background-color: #ffffe0; color: #800000">&quot;CustomNamespace&quot;</span><span style="background-color: #ffffe0; color: #000000">
  t.Render()
</span><span style="background-color: #ffd700; color: #000000">#&gt;</span></pre>
<h5><a href="http://www.olegsych.com/wp-content/uploads/2010/03/image7.png"><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="" border="0" alt="" align="right" src="http://www.olegsych.com/wp-content/uploads/2010/03/image-thumb2.png" width="272" height="80" /></a></h5>
<h4>Output.BuildProperties property</h4>
<p>For some types of files, such as resource files, not all project item attributes are exposed in Visual Studio user interface. In particular, resource files have a <em>LogicalName</em> attribute that determines the name under which the resource will be embedded in a .NET assembly. <em>BuildProperties</em> property of the <em>OutputInfo</em> class allows you to specify this and other MSBuild properties for the output file. <em>BuildProperties</em> is a string dictionary, you will need to know names of the properties you want to set. </p>
<h6>C#</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffd700; color: #000000">&lt;#</span><span style="background-color: #ffffe0; color: #000000">
  </span><span style="background-color: #ffffe0; color: #0000ff">var</span><span style="background-color: #ffffe0; color: #000000"> t = </span><span style="background-color: #ffffe0; color: #0000ff">new</span><span style="background-color: #ffffe0; color: #000000"> ResourceTemplate();
  t.Output.File = </span><span style="background-color: #ffffe0; color: #800000">&quot;Resource.resx&quot;</span><span style="background-color: #ffffe0; color: #000000">;
  t.Output.BuildProperties[</span><span style="background-color: #ffffe0; color: #800000">&quot;LogicalName&quot;</span><span style="background-color: #ffffe0; color: #000000">] = </span><span style="background-color: #ffffe0; color: #800000">&quot;MyResource&quot;</span><span style="background-color: #ffffe0; color: #000000">;
  t.Render();
</span><span style="background-color: #ffd700; color: #000000">#&gt;</span></pre>
<h6>VB</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffd700; color: #000000">&lt;#</span><span style="background-color: #ffffe0; color: #000000">
  </span><span style="background-color: #ffffe0; color: #0000ff">Dim</span><span style="background-color: #ffffe0; color: #000000"> t </span><span style="background-color: #ffffe0; color: #0000ff">as</span><span style="background-color: #ffffe0; color: #000000"> </span><span style="background-color: #ffffe0; color: #0000ff">New</span><span style="background-color: #ffffe0; color: #000000"> ResourceTemplate()
  t.Output.File = </span><span style="background-color: #ffffe0; color: #800000">&quot;Resource.resx&quot;</span><span style="background-color: #ffffe0; color: #000000">
  t.Output.BuildProperties(</span><span style="background-color: #ffffe0; color: #800000">&quot;LogicalName&quot;</span><span style="background-color: #ffffe0; color: #000000">) = </span><span style="background-color: #ffffe0; color: #800000">&quot;MyResource&quot;</span><span style="background-color: #ffffe0; color: #000000">
  t.Render()
</span><span style="background-color: #ffd700; color: #000000">#&gt;</span></pre>
<h5><img style="border-bottom: 0px; border-left: 0px; margin: 0px 0px 0px 5px; display: inline; border-top: 0px; border-right: 0px" title="" border="0" alt="" align="right" src="http://www.olegsych.com/wp-content/uploads/2010/03/image17.png" width="200" height="115" /> </h5>
<h4>Output.References property</h4>
<p><em>References</em> property of the <em>OutputInfo </em>class specifies the assembly references that needed for the generated file to compile. <em>References</em> is a collection of strings, empty by default. The following example illustrates a scenario where the generated output uses Oracle client and needs a reference to <em>System.Data.OracleClient </em>assembly to compile. When the template is rendered, T4 Toolbox will automatically add the specified reference(s) to the target project.</p>
<h6>C#</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffd700; color: #000000">&lt;#</span><span style="background-color: #ffffe0; color: #000000">
  </span><span style="background-color: #ffffe0; color: #0000ff">var</span><span style="background-color: #ffffe0; color: #000000"> t = </span><span style="background-color: #ffffe0; color: #0000ff">new</span><span style="background-color: #ffffe0; color: #000000"> OracleTemplate();
  t.Output.File = </span><span style="background-color: #ffffe0; color: #800000">&quot;OracleCode.cs&quot;</span><span style="background-color: #ffffe0; color: #000000">;
  t.Output.References.Add(</span><span style="background-color: #ffffe0; color: #800000">&quot;System.Data.OracleClient&quot;</span><span style="background-color: #ffffe0; color: #000000">);
  t.Render();
</span><span style="background-color: #ffd700; color: #000000">#&gt;</span></pre>
<h6>VB</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffd700; color: #000000">&lt;#</span><span style="background-color: #ffffe0; color: #000000">
  </span><span style="background-color: #ffffe0; color: #0000ff">Dim</span><span style="background-color: #ffffe0; color: #000000"> t </span><span style="background-color: #ffffe0; color: #0000ff">as</span><span style="background-color: #ffffe0; color: #000000"> </span><span style="background-color: #ffffe0; color: #0000ff">New</span><span style="background-color: #ffffe0; color: #000000"> OracleTemplate()
  t.Output.File = </span><span style="background-color: #ffffe0; color: #800000">&quot;OracleCode.vb&quot;</span><span style="background-color: #ffffe0; color: #000000">
  t.Output.References.Add(</span><span style="background-color: #ffffe0; color: #800000">&quot;System.Data.OracleClient&quot;</span><span style="background-color: #ffffe0; color: #000000">)
  t.Render()
</span><span style="background-color: #ffd700; color: #000000">#&gt;</span></pre>
<h5><img style="border-bottom: 0px; border-left: 0px; margin: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" align="right" src="http://www.olegsych.com/wp-content/uploads/2010/03/image18.png" width="180" height="126" /></h5>
<h4>Output.PreserveExistingFile property</h4>
<p><em>PreserveExistingFile</em> is a boolean property of the <em>OutputInfo </em>class. It is <em>false </em>by default, which means that T4 Toolbox will treat the output file as automatically generated, under full control of the generator. When <em>PreserveExistingFile </em>is true, T4 Toolbox will treat the output file as optionally generated, under full control of the developer. If the file already exists before code generation, the framework will assume that developer created it manually and will not overwrite it. When the file is no longer generated, the framework will again assume that developer modified it and will not delete the file. This logic is designed to preserve code written by hand. </p>
<p>Setting this property to true allows you to generate scaffolding code - code meant to serve as a sample or starting point for a developer to complete manually, such as partial classes or stubs. </p>
<h6>C#</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffd700; color: #000000">&lt;#</span><span style="background-color: #ffffe0; color: #000000">
  </span><span style="background-color: #ffffe0; color: #0000ff">var</span><span style="background-color: #ffffe0; color: #000000"> t = </span><span style="background-color: #ffffe0; color: #0000ff">new</span><span style="background-color: #ffffe0; color: #000000"> SampleTemplate();
  t.Output.File = </span><span style="background-color: #ffffe0; color: #800000">&quot;Sample.cs&quot;</span><span style="background-color: #ffffe0; color: #000000">;
  t.Output.PreserveExistingFile = </span><span style="background-color: #ffffe0; color: #0000ff">true</span><span style="background-color: #ffffe0; color: #000000">;
  t.Render();
</span><span style="background-color: #ffd700; color: #000000">#&gt;</span></pre>
<h6>VB</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffd700; color: #000000">&lt;#</span><span style="background-color: #ffffe0; color: #000000">
  </span><span style="background-color: #ffffe0; color: #0000ff">Dim</span><span style="background-color: #ffffe0; color: #000000"> t </span><span style="background-color: #ffffe0; color: #0000ff">as</span><span style="background-color: #ffffe0; color: #000000"> </span><span style="background-color: #ffffe0; color: #0000ff">New</span><span style="background-color: #ffffe0; color: #000000"> SampleTemplate()
  t.Output.File = </span><span style="background-color: #ffffe0; color: #800000">&quot;Sample.vb&quot;</span><span style="background-color: #ffffe0; color: #000000">
  t.Output.PreserveExistingFile = </span><span style="background-color: #ffffe0; color: #0000ff">True</span><span style="background-color: #ffffe0; color: #000000">
  t.Render()
</span><span style="background-color: #ffd700; color: #000000">#&gt;</span></pre>
<h4>Download</h4>
<p><a href="http://www.olegsych.com/wp-content/uploads/2010/03/t4-tutorial-integrating-generated-files-in-visual-studio-projects.zip">Source code, C# and Visual Basic</a>.</p>
<p>&copy;2012 <a href="http://www.olegsych.com">Oleg Sych</a>. All Rights Reserved.</p>.<img src="http://feeds.feedburner.com/~r/olegsych/~4/L8drOpvisAE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.olegsych.com/2010/03/t4-tutorial-integrating-generated-files-in-visual-studio-projects/feed/</wfw:commentRss>
		</item>
		<item>
		<title>UML Modeling and Code Generation in Visual Studio 2010</title>
		<link>http://www.olegsych.com/2010/01/uml-modeling-and-code-generation-in-visual-studio-2010/</link>
		<comments>http://www.olegsych.com/2010/01/uml-modeling-and-code-generation-in-visual-studio-2010/#comments</comments>
		<pubDate>Sun, 17 Jan 2010 22:47:42 +0000</pubDate>
		<dc:creator>Oleg Sych</dc:creator>
		
		<category><![CDATA[Articles]]></category>

		<category><![CDATA[Code Generation]]></category>

		<category><![CDATA[T4]]></category>

		<category><![CDATA[UML]]></category>

		<category><![CDATA[Visual Studio]]></category>

		<guid isPermaLink="false">http://www.olegsych.com/2010/01/uml-modeling-and-code-generation-in-visual-studio-2010/</guid>
		<description><![CDATA[This article provides an overview of UML modeling in Visual Studio 2010. Assuming that reader is already familiar with UML, it focuses on custom UML profiles - an extensibility mechanism that can be used to tailor UML models to a particular problem domain. Readers will see an example of such a profile, which extends UML Class Diagrams for database modeling. Finally, the article shows how code can be generated from UML models using T4 text templates.]]></description>
			<content:encoded><![CDATA[<p>This article provides an overview of UML modeling in Visual Studio 2010. Assuming that reader is already familiar with UML, it focuses on custom UML profiles - an extensibility mechanism that can be used to tailor UML models to a particular problem domain. Readers will see an example of such a profile, which extends UML Class Diagrams for database modeling. Finally, the article shows how code can be generated from UML models using T4 text templates.</p>
<p>This article is based on Beta 2 of Visual Studio 2010 Ultimate Edition. To follow the code example you may also want to install <a target="_blank" href="http://www.olegsych.com/2009/04/t4-editor-by-tangible-engineering/">T4 Editor</a> which provides color syntax highlighting and IntelliSense for text templates in Visual Studio.</p>
<h4>UML Modeling in Visual Studio</h4>
<p>Visual Studio 2010 Ultimate Edition includes a fully-featured UML (Unified Modeling Language) support, integrated into the IDE. You can create <a target="_blank" href="http://msdn.microsoft.com/en-us/library/dd409432(VS.100).aspx">Use Case</a> diagrams to summarize who uses your application or system, and what they can do with it, <a target="_blank" href="http://msdn.microsoft.com/en-us/library/dd409416(VS.100).aspx">Class</a> diagrams to describe logical aspects of data types and their relationships, <a target="_blank" href="http://msdn.microsoft.com/en-us/library/dd409389(VS.100).aspx">Sequence</a> diagrams to display interaction between classes, components and actors, <a target="_blank" href="http://msdn.microsoft.com/en-us/library/dd409465(VS.100).aspx">Activity</a> diagrams to document flow of an algorithm or a business process and <a target="_blank" href="http://msdn.microsoft.com/en-us/library/dd409393(VS.100).aspx">Component</a> diagrams to show structure of a system, and how it can be deployed to a logical environment.</p>
<p>In order to start using UML diagrams in Visual Studio 2010, you first need to create a <em>Modeling Project</em>.</p>
<p><img border="0" src="http://www.olegsych.com/wp-content/uploads/2010/01/image.png" style="display: inline; border-width: 0px" height="326" width="580" /></p>
<p>Once you have the project created, you can add new diagrams to it.</p>
<p><img border="0" src="http://www.olegsych.com/wp-content/uploads/2010/01/image1.png" style="display: inline; border-width: 0px" height="326" width="580" /></p>
<p>Here is an example of class diagram you can create.</p>
<p><img border="0" src="http://www.olegsych.com/wp-content/uploads/2010/01/image2.png" style="display: inline; border-width: 0px" height="522" width="580" /></p>
<p>Model elements can be added to the diagram from Toolbox and configured using Properties window.</p>
<p><img border="0" src="http://www.olegsych.com/wp-content/uploads/2010/01/image3.png" style="display: inline; border-width: 0px" height="375" width="282" /> <img border="0" src="http://www.olegsych.com/wp-content/uploads/2010/01/image4.png" style="display: inline; border-width: 0px" height="375" width="285" /> </p>
<p>You may have noticed that these diagrams are very similar to the sample diagrams that were included with the <a target="_blank" href="http://msdn.microsoft.com/en-us/library/bb126235.aspx">DSL (Domain-Specific Language) Toolkit</a> in Visual Studio 2008. While little has changed on the surface, DSL diagrams had a major limitation before Visual Studio 2010. Model information was stored with each diagram, limiting you to a single diagram per model. Needless to say, this limitation made it impossible to use DSL diagrams for all but simplest models.</p>
<p>In Visual Studio 2010, definitions of model elements are stored in a centralized repository as part of your Modeling Project; they can be displayed on multiple diagrams. You can browse contents of the repository using <em>UML Model Explorer</em> and add existing elements to new diagrams by dragging them from this window onto the design surface.</p>
<p><img border="0" src="http://www.olegsych.com/wp-content/uploads/2010/01/image5.png" style="display: inline; border-width: 0px" height="207" width="282" /> <img border="0" src="http://www.olegsych.com/wp-content/uploads/2010/01/image6.png" style="display: inline; border-width: 0px" height="207" width="282" /></p>
<h5>UML Profiles</h5>
<p>While UML works well for conceptual analysis, the standard models are often too abstract to be useful for logical and physical design. <em>UML Profiles </em>can be used to extend the standard models and adapt them for a particular purpose.</p>
<p>In Visual Studio 2010, a UML Profile is a collection of stereotypes that can be applied to individual model elements. Each stereotype defines a set of attributes that extend definition of the model element it is applied to. For example, Visual Studio includes <em>C# Profile</em> that can be used to extend UML classes with attributes specific to C#.</p>
<p>In order to use stereotypes from a particular profile, first you need to select a package in the <em>UML Model Explorer </em>and apply the profile in the <em>Properties </em>window.</p>
<p><img border="0" src="http://www.olegsych.com/wp-content/uploads/2010/01/image7.png" style="display: inline; border-width: 0px" height="374" width="283" /> <img border="0" src="http://www.olegsych.com/wp-content/uploads/2010/01/image8.png" style="margin: 0px 5px 0px 0px; display: inline; border-width: 0px" height="374" width="283" /></p>
<p>Once a profile has been specified for the package, you can apply the stereotypes defined by the profile to the elements within the package. Example below shows the <em>C# Class</em> stereotype applied to a UML class, extending it with C#-specific attributes, such as <em>Is Partial</em> and <em>Is Static</em>.</p>
<p><img border="0" src="http://www.olegsych.com/wp-content/uploads/2010/01/image9.png" style="display: block; float: none; margin-left: auto; margin-right: auto; border-width: 0px" height="374" width="472" /></p>
<h5>Custom UML Profiles</h5>
<p>You may want to consider creating a custom UML profile if you rely heavily on modeling in your software development project. Database modeling in particular has been widely adopted by the IT industry, with most of the new projects using database models in some shape or fashion. Unfortunately, no standard UML profile is available for database modeling at the time of this writing. However, the process of creating such a profile in Visual Studio 2010 is relatively straightforward.</p>
<p>Visual Studio 2010 UML profiles are defined in XML files with <em>.profile</em> extension.</p>
<p><img border="0" src="http://www.olegsych.com/wp-content/uploads/2010/01/image10.png" style="display: inline; border-width: 0px" height="477" width="580" /></p>
<p>The profile definition consists of three sections: <em>metaclasses</em>, <em>propertyTypes</em> and <em>stereotypes</em>.</p>
<p>The <em>metaclasses </em>section lists all UML meta-classes that are extended by stereotypes in the profile. In practical terms, meta-class is a type of model element, such as Package, Class or Association. Meta-classes are identified using fully-qualified type names of the interfaces used in Visual Studio implementation. For example, <a target="_blank" href="http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.uml.classes.iassociation(VS.100).aspx">IAssociation</a> interface represents UML meta-class Association.</p>
<p>The <em>propertyTypes</em> section lists all types used by properties in stereotypes defined by the profile. Standard types, such as <em>System.String</em> can be specified using <em>externalType</em> element. You can also use <em>enumerationType</em> elements to define enumerated types, such as <em>ForeignKeyRule.</em></p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">enumerationType </span><span style="color: red">name</span><span style="color: blue">=</span>&#8220;<span style="color: blue">ForeignKeyRule</span>&#8220;<span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">enumerationLiterals</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">enumerationLiteral </span><span style="color: red">name</span><span style="color: blue">=</span>&#8220;<span style="color: blue">NoAction</span>&#8221; <span style="color: red">displayName</span><span style="color: blue">=</span>&#8220;<span style="color: blue">No Action</span>&#8220;<span style="color: blue">/&gt;
    &lt;</span><span style="color: #a31515">enumerationLiteral </span><span style="color: red">name</span><span style="color: blue">=</span>&#8220;<span style="color: blue">Cascade</span>&#8221; <span style="color: red">displayName</span><span style="color: blue">=</span>&#8220;<span style="color: blue">Cascade</span>&#8220;<span style="color: blue">/&gt;
    &lt;</span><span style="color: #a31515">enumerationLiteral </span><span style="color: red">name</span><span style="color: blue">=</span>&#8220;<span style="color: blue">SetNull</span>&#8221; <span style="color: red">displayName</span><span style="color: blue">=</span>&#8220;<span style="color: blue">Set Null</span>&#8220;<span style="color: blue">/&gt;
    &lt;</span><span style="color: #a31515">enumerationLiteral </span><span style="color: red">name</span><span style="color: blue">=</span>&#8220;<span style="color: blue">SetDefault</span>&#8221; <span style="color: red">displayName</span><span style="color: blue">=</span>&#8220;<span style="color: blue">Set Default</span>&#8220;<span style="color: blue">/&gt;
  &lt;/</span><span style="color: #a31515">enumerationLiterals</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">enumerationType</span><span style="color: blue">&gt;
</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>Finally, the <em>stereotypes</em> section contains the actual stereotype definitions. Each stereotype contains a <em>metaclasses</em> element, which specifies the UML meta-class this stereotype extends, and a <em>properties</em> element, which lists the properties that will be added to the target model element when the stereotype is applied to it. </p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">stereotype </span><span style="color: red">name</span><span style="color: blue">=</span>&#8220;<span style="color: blue">ForeignKey</span>&#8221; <span style="color: red">displayName</span><span style="color: blue">=</span>&#8220;<span style="color: blue">Foreign Key</span>&#8220;<span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">metaclasses</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">metaclassMoniker </span><span style="color: red">name</span><span style="color: blue">=</span>&#8220;<span style="color: blue">/Sql2008DatabaseProfile/Microsoft.VisualStudio.Uml.Classes.IAssociation</span>&#8221; <span style="color: blue">/&gt;
  &lt;/</span><span style="color: #a31515">metaclasses</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">properties</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">property </span><span style="color: red">name</span><span style="color: blue">=</span>&#8220;<span style="color: blue">DeleteRule</span>&#8221; <span style="color: red">displayName</span><span style="color: blue">=</span>&#8220;<span style="color: blue">Delete Rule</span>&#8221; <span style="color: red">defaultValue</span><span style="color: blue">=</span>&#8220;<span style="color: blue">NoAction</span>&#8220;<span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">propertyType</span><span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">enumerationTypeMoniker </span><span style="color: red">name</span><span style="color: blue">=</span>&#8220;<span style="color: blue">/Sql2008DatabaseProfile/ForeignKeyRule</span>&#8220;<span style="color: blue">/&gt;
      &lt;/</span><span style="color: #a31515">propertyType</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">property</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">property </span><span style="color: red">name</span><span style="color: blue">=</span>&#8220;<span style="color: blue">UpdateRule</span>&#8221; <span style="color: red">displayName</span><span style="color: blue">=</span>&#8220;<span style="color: blue">Update Rule</span>&#8221; <span style="color: red">defaultValue</span><span style="color: blue">=</span>&#8220;<span style="color: blue">NoAction</span>&#8220;<span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">propertyType</span><span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">enumerationTypeMoniker </span><span style="color: red">name</span><span style="color: blue">=</span>&#8220;<span style="color: blue">/Sql2008DatabaseProfile/ForeignKeyRule</span>&#8220;<span style="color: blue">/&gt;
      &lt;/</span><span style="color: #a31515">propertyType</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">property</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">properties</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">stereotype</span><span style="color: blue">&gt;
</span></pre>
<p>As you can see, the <em>ForeignKey</em> stereotype shown above can be applied to Associations in a UML model. This stereotype defines two properties – <em>DeleteRule</em> and <em>UpdateRule</em>, both of which use the <em>ForeignKeyRule</em> enumerated type defined in the <em>propertyTypes</em> section of our profile.</p>
<p>Notice that various elements in the profile definition have attributes called <em>name </em>and <em>displayName</em>. As you might expect, <em>name</em> specifies internal identifier you can use to access values programmatically, and <em>displayName</em> specifies human-readable text displayed by Visual Studio to the developer.</p>
<h5>Sample Database Profile</h5>
<p>A sample UML profile for database modeling is available for download at the end of this article. It allows you to extend UML class diagrams with stereotypes for modeling database schemas, tables, columns, primary and foreign keys in SQL Server 2008. Here is what a database diagram developed with this profile might look like.</p>
<p><img border="0" src="http://www.olegsych.com/wp-content/uploads/2010/01/image11.png" style="display: inline; border-width: 0px" height="541" width="580" /></p>
<p>The sample database profile contains the following stereotypes.</p>
<table cellPadding="2" cellSpacing="0" border="1" width="100%">
<tr>
<td vAlign="top" width="115">
<h6>Stereotype</h6>
</td>
<td vAlign="top" width="113">
<h6>Schema</h6>
</td>
<td vAlign="top" width="106">
<h6>Table</h6>
</td>
<td vAlign="top" width="108">
<h6>Column</h6>
</td>
<td vAlign="top" width="110">
<h6>Foreign Key</h6>
</td>
</tr>
<tr>
<td vAlign="top" width="115">
<h6>Applies To</h6>
</td>
<td vAlign="top" width="112">Package</td>
<td vAlign="top" width="105">Class</td>
<td vAlign="top" width="108">Property</td>
<td vAlign="top" width="112">Association</td>
</tr>
<tr>
<td vAlign="top" width="115">
<h6>Properties</h6>
</td>
<td vAlign="top" width="112">Schema Name</td>
<td vAlign="top" width="105"> </td>
<td vAlign="top" width="108">Allow Nulls</p>
<p>Data TypeDefault Value</p>
<p>Is Identity</td>
<td vAlign="top" width="114">Update Rule</p>
<p>Delete Rule</td>
</tr>
</table>
<h5>Profile Installation</h5>
<p>The intended way to install custom UML Profiles is with the help of <a target="_blank" href="http://dotneteers.net/blogs/divedeeper/archive/2009/10/20/devtools-ecosystem-summit-deploying-visual-studio-2010-extensions.aspx">Visual Studio Extensions</a>, new to Visual Studio 2010. The process is well documented on <a target="_blank" href="http://msdn.microsoft.com/en-us/library/dd465143(VS.100).aspx">MSDN</a>, simple and easy to follow. Unfortunately, as of Visual Studio 2010 Beta 2, VSIX deployment of custom profiles appears to be broken. In order to install the sample database profile, I had to resort to manually copying the .profile file to the following directory on a 64-bit Windows 7 installation:</p>
<blockquote><p>C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\Microsoft\Team Architecture\UmlProfiles</p></blockquote>
<p>and modifying extension.vsixmanifest file located in this directory to look like this.</p>
<pre class="code"><span style="color: blue">&lt;?</span><span style="color: #a31515">xml </span><span style="color: red">version</span><span style="color: blue">=</span>&#8220;<span style="color: blue">1.0</span>&#8221; <span style="color: red">encoding</span><span style="color: blue">=</span>&#8220;<span style="color: blue">utf-8</span>&#8220;<span style="color: blue">?&gt;
&lt;</span><span style="color: #a31515">Vsix </span><span style="color: red">Version</span><span style="color: blue">=</span>&#8220;<span style="color: blue">1.0.0</span>&#8221; <span style="color: red">xmlns</span><span style="color: blue">=</span>&#8220;<span style="color: blue">http://schemas.microsoft.com/developer/vsx-schema/2010</span>&#8220;<span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">Identifier </span><span style="color: red">Id</span><span style="color: blue">=</span>&#8220;<span style="color: blue">Microsoft.VisualStudio.TeamArchitect.ProfileExtension</span>&#8220;<span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">Name</span><span style="color: blue">&gt;</span>Team Architecture Profile Extension<span style="color: blue">&lt;/</span><span style="color: #a31515">Name</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">Author</span><span style="color: blue">&gt;</span>Microsoft<span style="color: blue">&lt;/</span><span style="color: #a31515">Author</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">Version</span><span style="color: blue">&gt;</span>10.0<span style="color: blue">&lt;/</span><span style="color: #a31515">Version</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">Description</span><span style="color: blue">&gt;</span>Microsoft Visual Studio Team Architecture Profile Extension<span style="color: blue">&lt;/</span><span style="color: #a31515">Description</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">Locale</span><span style="color: blue">&gt;</span>1033<span style="color: blue">&lt;/</span><span style="color: #a31515">Locale</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">SupportedProducts</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">VisualStudio </span><span style="color: red">Version</span><span style="color: blue">=</span>&#8220;<span style="color: blue">10.0</span>&#8220;<span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">Edition</span><span style="color: blue">&gt;</span>VSTS<span style="color: blue">&lt;/</span><span style="color: #a31515">Edition</span><span style="color: blue">&gt;
      &lt;/</span><span style="color: #a31515">VisualStudio</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">SupportedProducts</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">SupportedFrameworkRuntimeEdition </span><span style="color: red">MinVersion</span><span style="color: blue">=</span>&#8220;<span style="color: blue">4.0</span>&#8221; <span style="color: red">MaxVersion</span><span style="color: blue">=</span>&#8220;<span style="color: blue">4.0</span>&#8221; <span style="color: blue">/&gt;
    &lt;</span><span style="color: #a31515">SystemComponent</span><span style="color: blue">&gt;</span>true<span style="color: blue">&lt;/</span><span style="color: #a31515">SystemComponent</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">Identifier</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">References </span><span style="color: blue">/&gt;
  &lt;</span><span style="color: #a31515">Content</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">CustomExtension </span><span style="color: red">Type</span><span style="color: blue">=</span>&#8220;<span style="color: blue">Microsoft.VisualStudio.UmlProfile</span>&#8220;<span style="color: blue">&gt;</span>CSharp.Profile<span style="color: blue">&lt;/</span><span style="color: #a31515">CustomExtension</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">CustomExtension </span><span style="color: red">Type</span><span style="color: blue">=</span>&#8220;<span style="color: blue">Microsoft.VisualStudio.UmlProfile</span>&#8220;<span style="color: blue">&gt;</span>StandardProfileL2.Profile<span style="color: blue">&lt;/</span><span style="color: #a31515">CustomExtension</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">CustomExtension </span><span style="color: red">Type</span><span style="color: blue">=</span>&#8220;<span style="color: blue">Microsoft.VisualStudio.UmlProfile</span>&#8220;<span style="color: blue">&gt;</span>StandardProfileL3.Profile<span style="color: blue">&lt;/</span><span style="color: #a31515">CustomExtension</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">CustomExtension </span><span style="color: red">Type</span><span style="color: blue">=</span>&#8220;<span style="color: blue">Microsoft.VisualStudio.UmlProfile</span>&#8220;<span style="color: blue">&gt;</span>Sql2008Database.profile<span style="color: blue">&lt;/</span><span style="color: #a31515">CustomExtension</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">Content</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">Vsix</span><span style="color: blue">&gt;
</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>Notice the <em>CustomExtension</em> added in the end of the file, specifying <em>Sql2008Database.profile</em> as an extension of <em>Microsoft.VisualStudio.UmlProfile</em> type.</p>
<h4>Code Generation</h4>
<p>The simplest way to generate code from a UML model is with the help of <a target="_blank" href="http://www.olegsych.com/2007/12/text-template-transformation-toolkit/">T4</a> text templates. Text template is a simple code generator that can be added to any C# and Visual Basic project.</p>
<p><img border="0" src="http://www.olegsych.com/wp-content/uploads/2010/01/image12.png" style="display: inline; border-width: 0px" height="315" width="560" /></p>
<p>Here is the code you need to have in your template to load metadata from a UML model.</p>
<pre style="background-color: white" class="code"><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">template</span><span style="color: #000000"> </span><span style="color: #ff0000">debug</span><span style="color: #000000">=</span><span style="color: #000000">&#8220;</span><span style="color: #0000ff">true</span><span style="color: #000000">&#8220;</span><span style="color: #000000"> </span><span style="color: #ff0000">hostspecific</span><span style="color: #000000">=</span><span style="color: #000000">&#8220;</span><span style="color: #0000ff">true</span><span style="color: #000000">&#8220;</span><span style="color: #000000"> </span><span style="color: #ff0000">language</span><span style="color: #000000">=</span><span style="color: #000000">&#8220;</span><span style="color: #0000ff">C#</span><span style="color: #000000">&#8220;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">output</span><span style="color: #000000"> </span><span style="color: #ff0000">extension</span><span style="color: #000000">=</span><span style="color: #000000">&#8220;</span><span style="color: #0000ff">.sql</span><span style="color: #000000">&#8220;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">assembly</span><span style="color: #000000"> </span><span style="color: #ff0000">name</span><span style="color: #000000">=</span><span style="color: #000000">&#8220;</span><span style="color: #0000ff">Microsoft.VisualStudio.Uml.Interfaces.dll</span><span style="color: #000000">&#8220;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">assembly</span><span style="color: #000000"> </span><span style="color: #ff0000">name</span><span style="color: #000000">=</span><span style="color: #000000">&#8220;</span><span style="color: #0000ff">Microsoft.VisualStudio.Uml.Extensions.dll</span><span style="color: #000000">&#8220;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">import</span><span style="color: #000000"> </span><span style="color: #ff0000">namespace</span><span style="color: #000000">=</span><span style="color: #000000">&#8220;</span><span style="color: #0000ff">Microsoft.VisualStudio.Uml.Classes</span><span style="color: #000000">&#8220;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">import</span><span style="color: #000000"> </span><span style="color: #ff0000">namespace</span><span style="color: #000000">=</span><span style="color: #000000">&#8220;</span><span style="color: #0000ff">Microsoft.VisualStudio.Uml.Extensions</span><span style="color: #000000">&#8220;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#</span><span style="background-color: #ffffe0; color: #000000">
    </span><span style="background-color: #ffffe0; color: #0000ff">string</span><span style="background-color: #ffffe0; color: #000000"> projectPath = </span><span style="background-color: #ffffe0; color: #000000">Host.ResolvePath(</span><span style="background-color: #ffffe0; color: #800000">@&#8221;..\ModelingProject\ModelingProject.modelproj&#8221;</span><span style="background-color: #ffffe0; color: #000000">);
    IModelingProject project = ModelingProject.Load(projectPath);
</span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="background-color: #ffd700; color: #000000">
</span></pre>
<p>Notice the use of <a target="_blank" href="http://www.olegsych.com/2008/02/t4-assembly-directive/">assembly</a> and <a target="_blank" href="http://www.olegsych.com/2008/02/t4-import-directive/">import</a> directives to reference the Visual Studio assemblies and namespaces that provide API for accessing information in UML models. <a target="_blank" href="http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.texttemplating.itexttemplatingenginehost.resolvepath.aspx">ResolvePath</a> method of the <em>Host</em> object is used to determine absolute path to the modeling project and <a target="_blank" href="http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.uml.extensions.modelingproject.load(VS.100).aspx">Load</a> method of the <em>ModelingProject</em> class is used to open the UML repository.</p>
<p>Here is a complete template that generates SQL scripts for creating tables based on the UML class model extended by our database profile.</p>
<pre style="background-color: white" class="code"><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">template</span><span style="color: #000000"> </span><span style="color: #ff0000">debug</span><span style="color: #000000">=</span><span style="color: #000000">&#8220;</span><span style="color: #0000ff">true</span><span style="color: #000000">&#8220;</span><span style="color: #000000"> </span><span style="color: #ff0000">hostspecific</span><span style="color: #000000">=</span><span style="color: #000000">&#8220;</span><span style="color: #0000ff">true</span><span style="color: #000000">&#8220;</span><span style="color: #000000"> </span><span style="color: #ff0000">language</span><span style="color: #000000">=</span><span style="color: #000000">&#8220;</span><span style="color: #0000ff">C#</span><span style="color: #000000">&#8220;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">output</span><span style="color: #000000"> </span><span style="color: #ff0000">extension</span><span style="color: #000000">=</span><span style="color: #000000">&#8220;</span><span style="color: #0000ff">.sql</span><span style="color: #000000">&#8220;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">assembly</span><span style="color: #000000"> </span><span style="color: #ff0000">name</span><span style="color: #000000">=</span><span style="color: #000000">&#8220;</span><span style="color: #0000ff">System.Core</span><span style="color: #000000">&#8220;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">assembly</span><span style="color: #000000"> </span><span style="color: #ff0000">name</span><span style="color: #000000">=</span><span style="color: #000000">&#8220;</span><span style="color: #0000ff">Microsoft.VisualStudio.Uml.Interfaces.dll</span><span style="color: #000000">&#8220;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">assembly</span><span style="color: #000000"> </span><span style="color: #ff0000">name</span><span style="color: #000000">=</span><span style="color: #000000">&#8220;</span><span style="color: #0000ff">Microsoft.VisualStudio.Uml.Extensions.dll</span><span style="color: #000000">&#8220;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">import</span><span style="color: #000000"> </span><span style="color: #ff0000">namespace</span><span style="color: #000000">=</span><span style="color: #000000">&#8220;</span><span style="color: #0000ff">System.Linq</span><span style="color: #000000">&#8220;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">import</span><span style="color: #000000"> </span><span style="color: #ff0000">namespace</span><span style="color: #000000">=</span><span style="color: #000000">&#8220;</span><span style="color: #0000ff">Microsoft.VisualStudio.Uml.Classes</span><span style="color: #000000">&#8220;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">import</span><span style="color: #000000"> </span><span style="color: #ff0000">namespace</span><span style="color: #000000">=</span><span style="color: #000000">&#8220;</span><span style="color: #0000ff">Microsoft.VisualStudio.Uml.Extensions</span><span style="color: #000000">&#8220;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#</span><span style="background-color: #ffffff; color: #000000">
    </span><span style="background-color: #ffffe0; color: #0000ff">string</span><span style="background-color: #ffffe0; color: #000000"> projectPath = </span><span style="background-color: #ffffe0; color: #0000ff">this</span><span style="background-color: #ffffe0; color: #000000">.Host.ResolvePath(</span><span style="background-color: #ffffe0; color: #800000">@&#8221;..\ModelingProject\ModelingProject.modelproj&#8221;</span><span style="background-color: #ffffe0; color: #000000">);
    IModelingProject project = ModelingProject.Load(projectPath);
    </span><span style="background-color: #ffffe0; color: #0000ff">foreach</span><span style="background-color: #ffffe0; color: #000000"> (IType t </span><span style="background-color: #ffffe0; color: #0000ff">in</span><span style="background-color: #ffffe0; color: #000000"> project.Store.Root.OwnedTypes)
    {
        IClass c = t </span><span style="background-color: #ffffe0; color: #0000ff">as</span><span style="background-color: #ffffe0; color: #000000"> IClass;
        </span><span style="background-color: #ffffe0; color: #0000ff">if</span><span style="background-color: #ffffe0; color: #000000"> (c == </span><span style="background-color: #ffffe0; color: #0000ff">null</span><span style="background-color: #ffffe0; color: #000000">) </span><span style="background-color: #ffffe0; color: #0000ff">continue</span><span style="background-color: #ffffe0; color: #000000">;
</span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="color: #0000ff">create</span><span style="color: #000000"> </span><span style="color: #0000ff">table</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">&lt;#=</span><span style="background-color: #ffffe0; color: #000000"> GetSchema(project.Store.Root) </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">.</span><span style="background-color: #ffd700; color: #000000">&lt;#=</span><span style="background-color: #ffffe0; color: #000000"> c.Name </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
(
</span><span style="background-color: #ffd700; color: #000000">&lt;#</span><span style="background-color: #ffffff; color: #000000">
        </span><span style="background-color: #ffffe0; color: #0000ff">this</span><span style="background-color: #ffffe0; color: #000000">.PushIndent(</span><span style="background-color: #ffffe0; color: #800000">&#8220;\t&#8221;</span><span style="background-color: #ffffe0; color: #000000">);
        </span><span style="background-color: #ffffe0; color: #0000ff">foreach</span><span style="background-color: #ffffe0; color: #000000"> (IProperty p </span><span style="background-color: #ffffe0; color: #0000ff">in</span><span style="background-color: #ffffe0; color: #000000"> c.OwnedAttributes)
        {
            IStereotypeInstance column = p.AppliedStereotypes.Where(s =&gt; s.Name == </span><span style="background-color: #ffffe0; color: #800000">&#8220;Column&#8221;</span><span style="background-color: #ffffe0; color: #000000">).First();
            </span><span style="background-color: #ffffe0; color: #0000ff">this</span><span style="background-color: #ffffe0; color: #000000">.WriteLine(p.Name + </span><span style="background-color: #ffffe0; color: #800000">&#8221; &#8220;</span><span style="background-color: #ffffe0; color: #000000"> + GetDataType(column) + GetNull(column) + GetIdentity(column) + </span><span style="background-color: #ffffe0; color: #800000">&#8220;,&#8221;</span><span style="background-color: #ffffe0; color: #000000">);
        }
        </span><span style="background-color: #ffffe0; color: #0000ff">this</span><span style="background-color: #ffffe0; color: #000000">.PopIndent();
</span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
);
</span><span style="background-color: #ffd700; color: #000000">&lt;#</span><span style="background-color: #ffffff; color: #000000">
    }
</span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#+</span><span style="background-color: #ffffff; color: #000000">
    </span><span style="background-color: #ffffe0; color: #0000ff">private</span><span style="background-color: #ffffe0; color: #000000"> </span><span style="background-color: #ffffe0; color: #0000ff">string</span><span style="background-color: #ffffe0; color: #000000"> GetSchema(IPackage package)
    {
        IStereotypeInstance schema = package.AppliedStereotypes.Where(s =&gt; s.Name == </span><span style="background-color: #ffffe0; color: #800000">&#8220;Schema&#8221;</span><span style="background-color: #ffffe0; color: #000000">).First();
        IStereotypePropertyInstance schemaName = schema.PropertyInstances.Where(p =&gt; p.Name == </span><span style="background-color: #ffffe0; color: #800000">&#8220;Name&#8221;</span><span style="background-color: #ffffe0; color: #000000">).First();
        </span><span style="background-color: #ffffe0; color: #0000ff">return</span><span style="background-color: #ffffe0; color: #000000"> schemaName.Value;
    } 

    </span><span style="background-color: #ffffe0; color: #0000ff">private</span><span style="background-color: #ffffe0; color: #000000"> </span><span style="background-color: #ffffe0; color: #0000ff">string</span><span style="background-color: #ffffe0; color: #000000"> GetDataType(IStereotypeInstance column)
    {
        IStereotypePropertyInstance dataType = column.PropertyInstances.Where(p =&gt; p.Name == </span><span style="background-color: #ffffe0; color: #800000">&#8220;DataType&#8221;</span><span style="background-color: #ffffe0; color: #000000">).First();
        </span><span style="background-color: #ffffe0; color: #0000ff">return</span><span style="background-color: #ffffe0; color: #000000"> dataType.Value;
    } 

    </span><span style="background-color: #ffffe0; color: #0000ff">private</span><span style="background-color: #ffffe0; color: #000000"> </span><span style="background-color: #ffffe0; color: #0000ff">string</span><span style="background-color: #ffffe0; color: #000000"> GetNull(IStereotypeInstance column)
    {
        IStereotypePropertyInstance allowNulls = column.PropertyInstances.Where(p =&gt; p.Name == </span><span style="background-color: #ffffe0; color: #800000">&#8220;AllowNulls&#8221;</span><span style="background-color: #ffffe0; color: #000000">).First();
        </span><span style="background-color: #ffffe0; color: #0000ff">return</span><span style="background-color: #ffffe0; color: #000000"> </span><span style="background-color: #ffffe0; color: #0000ff">bool</span><span style="background-color: #ffffe0; color: #000000">.Parse(allowNulls.Value) == </span><span style="background-color: #ffffe0; color: #0000ff">true</span><span style="background-color: #ffffe0; color: #000000"> ? </span><span style="background-color: #ffffe0; color: #0000ff">string</span><span style="background-color: #ffffe0; color: #000000">.Empty : </span><span style="background-color: #ffffe0; color: #800000">&#8221; not null&#8221;</span><span style="background-color: #ffffe0; color: #000000">;
    } 

    </span><span style="background-color: #ffffe0; color: #0000ff">private</span><span style="background-color: #ffffe0; color: #000000"> </span><span style="background-color: #ffffe0; color: #0000ff">string</span><span style="background-color: #ffffe0; color: #000000"> GetIdentity(IStereotypeInstance column)
    {
        IStereotypePropertyInstance isIdentity = column.PropertyInstances.Where(p =&gt; p.Name == </span><span style="background-color: #ffffe0; color: #800000">&#8220;IsIdentity&#8221;</span><span style="background-color: #ffffe0; color: #000000">).First();
        </span><span style="background-color: #ffffe0; color: #0000ff">return</span><span style="background-color: #ffffe0; color: #000000"> </span><span style="background-color: #ffffe0; color: #0000ff">bool</span><span style="background-color: #ffffe0; color: #000000">.Parse(isIdentity.Value) == </span><span style="background-color: #ffffe0; color: #0000ff">true</span><span style="background-color: #ffffe0; color: #000000"> ? </span><span style="background-color: #ffffe0; color: #800000">&#8221; identity&#8221;</span><span style="background-color: #ffffe0; color: #000000"> : </span><span style="background-color: #ffffe0; color: #0000ff">string</span><span style="background-color: #ffffe0; color: #000000">.Empty;
    }
</span><span style="background-color: #ffd700; color: #000000">#&gt;
</span></pre>
<p>This code uses a foreach loop to iterate through the list of types owned by the <a target="_blank" href="http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.uml.extensions.imodelstore.root(VS.100).aspx">Root</a> model in our project and generates a create table script for each class. Notice the helper methods, such as <em>GetSchema</em> and <em>GetDataType</em>. They use <a target="_blank" href="http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.uml.classes.ielement.appliedstereotypes(VS.100).aspx">AppliedStereotypes</a> property of the model element to find the stereotype defined in our database profile, such as <em>Schema</em> or <em>Column</em>. Having found the stereotype instance, its properties properties are accessed through the <a target="_blank" href="http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.uml.classes.istereotypeinstance.propertyinstances(VS.100).aspx">PropertyInstances</a> collection.</p>
<p>Here is the code generated by this text template from our UML model.</p>
<pre class="code"><span style="color: blue">create table </span><span style="color: teal">dbo</span><span style="color: gray">.</span><span style="color: teal">Customer
</span><span style="color: gray">(
    </span><span style="color: teal">FirstName </span><span style="color: blue">nvarchar</span><span style="color: gray">,
    </span><span style="color: teal">LastName </span><span style="color: blue">nvarchar</span><span style="color: gray">,
    </span><span style="color: teal">StreetAddress </span><span style="color: blue">nvarchar</span><span style="color: gray">,
    </span><span style="color: teal">City </span><span style="color: blue">nvarchar</span><span style="color: gray">,
    </span><span style="color: blue">State nvarchar</span><span style="color: gray">,
    </span><span style="color: teal">PostalCode </span><span style="color: blue">nvarchar</span><span style="color: gray">,
    </span><span style="color: teal">Id </span><span style="color: blue">int </span><span style="color: gray">not null </span><span style="color: blue">identity</span><span style="color: gray">,
);
</span><span style="color: blue">create table </span><span style="color: teal">dbo</span><span style="color: gray">.</span><span style="color: teal">Product
</span><span style="color: gray">(
    </span><span style="color: teal">Name </span><span style="color: blue">nvarchar</span><span style="color: gray">,
    </span><span style="color: teal">Price </span><span style="color: blue">nvarchar</span><span style="color: gray">,
    </span><span style="color: teal">Id </span><span style="color: blue">int </span><span style="color: gray">not null </span><span style="color: blue">identity</span><span style="color: gray">,
);
</span><span style="color: blue">create table </span><span style="color: teal">dbo</span><span style="color: gray">.</span><span style="color: blue">Order
</span><span style="color: gray">(
    </span><span style="color: blue">Date nvarchar</span><span style="color: gray">,
    </span><span style="color: teal">TotalAmount </span><span style="color: blue">nvarchar</span><span style="color: gray">,
    </span><span style="color: teal">Id </span><span style="color: blue">int </span><span style="color: gray">not null </span><span style="color: blue">identity</span><span style="color: gray">,
    </span><span style="color: teal">CustomerId </span><span style="color: blue">int</span><span style="color: gray">,
);
</span><span style="color: blue">create table </span><span style="color: teal">dbo</span><span style="color: gray">.</span><span style="color: teal">OrderItem
</span><span style="color: gray">(
    </span><span style="color: teal">Id </span><span style="color: blue">int </span><span style="color: gray">not null </span><span style="color: blue">identity</span><span style="color: gray">,
    </span><span style="color: teal">OrderId </span><span style="color: blue">int</span><span style="color: gray">,
    </span><span style="color: teal">ProductId </span><span style="color: blue">int</span><span style="color: gray">,
);</span></pre>
<h4>UML vs. DSL</h4>
<p>UML models are high-level abstractions, typically representing systems at conceptual or logical levels. This is an intentional, desired aspect, as it allows you to model a wide variety of of systems without tying the design to any particular platform or implementation. While high-level models serve as an excellent communication tool during envisioning and design phases, during implementation high-level models quickly become outdated, causing confusion. While automated code generation and reverse engineering of models is possible, the process is complex, fragile and requires additional effort.</p>
<p>Comprehensive support for UML is a significant change in direction of Microsoft’s approach to modeling. You may remember that when Domain-Specific Language tools were announced a few years ago, the emphasis was on practical application of modeling throughout the software development lifecycle. It was suggested that models should be considered equal to other source code artifacts, such as .cs/.vb files and .aspx pages. Typical DSL models are lower-level abstractions, representing a system at logical or physical levels. They are predominantly used for code generation and rely on partial classes and inheritance to avoid reverse engineering model information from code back to the model. Examples of DSL models in Visual Studio include LINQ to SQL and Entity Framework designers.</p>
<p>While these approaches to modeling appear to be different, in reality they complement each other, providing us with a full range of modeling capabilities from conceptual and logical, down to physical level. UML models are useful during early stages of a software development project and DSL models work best during implementation and maintenance of the system. It is interesting to note that UML models are actually implemented using DSL tools, so from Visual Studio prospective, UML is simply a DSL for the “unified modeling” domain.</p>
<h4>Conclusion</h4>
<p>As you can see, Visual Studio 2010 Ultimate Edition provides powerful UML modeling tools that can be used for conceptual and logical analysis during software development. UML Profiles can be used to extend standard models and allow modeling information systems at physical level. A limited number of UML profiles is expected to ship with Visual Studio 2010. Custom profiles can be developed to tailor UML models to the needs of individual projects. Combined with T4 Text Templates, this gives developers a powerful tools for model-driven development of information systems, where large portions of the system can be modeled in UML and generated with T4. </p>
<h4>References</h4>
<ul>
<li>MSDN, <a target="_blank" href="http://msdn.microsoft.com/en-us/library/dd409436(VS.100).aspx">Developing Models for Software Design</a></li>
<li>Cameron Skinner, <a target="_blank" href="http://blogs.msdn.com/camerons/archive/2010/01/08/uml-profiles-and-visual-studio-2010-ultimate-part-one.aspx">UML Profiles and Visual Studio 2010 Ultimate: Part One</a></li>
<li>Istvan Novak, <a target="_blank" href="http://dotneteers.net/blogs/divedeeper/archive/2009/10/20/devtools-ecosystem-summit-deploying-visual-studio-2010-extensions.aspx">Deploying Visual Studio 2010 Extensions, Part 1</a></li>
<li>Tim Fischer, <a target="_blank" href="http://blogs.msdn.com/timfis/archive/2009/10/31/how-to-generate-code-from-uml-diagrams-in-vs-2010-team-system-beta-2.aspx">How To: Generate Code from Team System UML Diagrams in VS 2010 Beta 2</a> </li>
<li>Oleg Sych, <a target="_blank" href="http://www.olegsych.com/2007/12/text-template-transformation-toolkit/">Text Template Transformation Toolkit</a></li>
</ul>
<h4>Download</h4>
<p><a target="_blank" href="http://www.olegsych.com/wp-content/uploads/2010/03/sql-2008-uml-profile.zip">Source code</a></p>
<p>&copy;2012 <a href="http://www.olegsych.com">Oleg Sych</a>. All Rights Reserved.</p>.<img src="http://feeds.feedburner.com/~r/olegsych/~4/mBElW5GhNTw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.olegsych.com/2010/01/uml-modeling-and-code-generation-in-visual-studio-2010/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Simplifying Entity Framework: Data-Driven Design</title>
		<link>http://www.olegsych.com/2009/12/simplifying-entity-framework-data-driven-design/</link>
		<comments>http://www.olegsych.com/2009/12/simplifying-entity-framework-data-driven-design/#comments</comments>
		<pubDate>Sun, 27 Dec 2009 20:42:00 +0000</pubDate>
		<dc:creator>Oleg Sych</dc:creator>
		
		<category><![CDATA[Articles]]></category>

		<category><![CDATA[ADO.NET]]></category>

		<category><![CDATA[C#]]></category>

		<category><![CDATA[Code Generation]]></category>

		<category><![CDATA[Entity Framework]]></category>

		<category><![CDATA[SQL]]></category>

		<category><![CDATA[T4]]></category>

		<category><![CDATA[VB]]></category>

		<category><![CDATA[Visual Studio]]></category>

		<guid isPermaLink="false">http://www.olegsych.com/2009/12/simplifying-entity-framework-data-driven-design/</guid>
		<description><![CDATA[This article reviews the theory and practice behind ADO.NET Entity Framework, discusses limitations of the current tools it provides and compares the benefits offered by solving the object-relational impedance mismatch against their costs. The article suggest using Entity Framework to improve and reduce costs of data-driven application design, which is prevalent in todays information systems and describes a code generation solution built using T4 Toolbox that can be used to achieve this goal.]]></description>
			<content:encoded><![CDATA[<p>As <a href="http://msdn.microsoft.com/en-us/library/bb399567.aspx">described on MSDN</a>, ADO.NET Entity Framework is a set of technologies that enables developers to work with data in the form of domain-specific objects and properties, such as customers and customer addresses without having to concern themselves with the underlying database tables and columns where this data is stored. Developers can use Entity SQL and traditional ADO.NET reader/adapter/dataset patterns or the new LINQ to Entities to write their code. With LINQ to Entities, the Entity Framework generates strongly-typed entity classes you can use in application code and rely on the runtime to figure out how the data needs to be retrieved from the underlying data source.</p>
<p><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="ADO.NET Entity Framework" border="0" alt="ADO.NET Entity Framework" src="http://www.olegsych.com/wp-content/uploads/2009/12/ado.netentityframework.gif" width="502" height="470" /></p>
<p>Design of Entity Framework has been inspired by the traditional methodology of relational database design which suggests creating a conceptual (class) model, transforming it into logical (relational) model and finally into physical database model. While these activities are typically performed during design and initial implementation of the information system, the Entity Framework implements the physical model, makes the conceptual model a first-class citizen and explicitly defines the mapping model.</p>
<ul>
<li>Conceptual model defines entities and their relationships from the application point of view. This model is defined using Conceptual Schema Definition Language (CSDL) and stored in a separate .csdl file or as part of a combined .edmx file in your project. </li>
<li>Storage model defines entities and their relationships from the database point of view. This model is defined using Store Schema Definition Language (SSDL) and stored in a separate .ssdl file or as part of a combined .edmx file in your project. </li>
<li>Mapping model defines how conceptual model translates into storage model. It is defined using Mapping Specification Language (MSL) and stored in a separate .msl file or as part of a combined .edmx file in your project. </li>
</ul>
<p>The Entity Framework uses these XML-based models to transform create, read, update, and delete operations against entities and relationships in the conceptual model to equivalent operations in the data source. The storage and mapping models can change as needed without requiring changes to the conceptual model, data classes, or application code. Because storage models are provider-specific, you can work with a consistent conceptual model across various data sources. The Entity Data Model even supports mapping entities in the conceptual model to stored procedures in the data source.</p>
<h4>What is wrong with this picture?</h4>
<p>Entity Framework was designed to overcome the <a href="http://en.wikipedia.org/wiki/Object-relational_impedance_mismatch">object-relational impedance mismatch</a> and allow you to hide a difficult-to-use legacy database schema behind a modern, object-oriented entity model and make developers more productive. This description almost sounds to good to be true. Unfortunately, just like other frameworks designed to solve complex problems, the Entity Framework tends to make simple things difficult.</p>
<p>Having three separate database layers (or models) in the Entity Data Model means having each entity represented three times, each from a different point of view. Every time you need to make a change in your database model, which also needs to be implemented in the application, you have to make it three times. Take adding a new column to a table as an example. No matter in which order you do it, you still have to add a new property to the conceptual model, a new column to the storage model and a new mapping from one to the other. This task is tedious and error prone even with the best modeling tools imaginable. Unfortunately, Entity Framework designer limits you to a single diagram, which gradually becomes more difficult to use as the number of entities increases, becoming virtually useless when it exceeds 50.</p>
<p>In simplistic terms, this all means that Entity Data Model is three times as complex as a traditional database model. To implement all but trivial logic, either one developer has to understand all three models or you have to have two or more people involved in implementing it. In the end, you have to spend three times more effort to develop and maintain the EDM, you are three times more likely to make mistakes, i.e. the cost of having the EDM in your solutions is three times higher than the cost of a solution that uses a single hypothetical data model.</p>
<h4>What is the alternative?</h4>
<p>Majority of information systems in existence today are built using relational databases and data-oriented code. A tremendous amount of tooling, knowledge and experience has been developed over the past two decades by the industry, making low-cost development resources readily available. Although solving the object-relational impedance mismatch sounds very good in theory, in practice, the overall cost of such a solution is typically higher, in part due to additional effort required to maintain three separate database models and in part due to additional knowledge and experience required from developers.</p>
<p>However, the existing as well as new information systems could benefit tremendously from having a modern, strongly-typed, LINQ-enabled, automatically generated data access layer (DAL). Such a DAL would allow to significantly reduce the amount of plumbing code developers have to write today with <a href="http://msdn.microsoft.com/en-us/library/system.data.common.dbconnection.aspx">DbConnection</a>, <a href="http://msdn.microsoft.com/en-us/library/system.data.common.dbdatareader.aspx">DbDataReader</a> and <a href="http://msdn.microsoft.com/en-us/library/system.data.dataset.aspx">DataSet</a> classes without requiring significant changes to the application architecture. In other words, as long as the effort required to maintain such a DAL is less than the effort required to maintain the data access code manually, we can take advantage of the language and data access enhancements offered by the current version of the .NET framework while reducing the overall cost of the information systems.</p>
<h4>Entity Framework DAL generator in T4 Toolbox</h4>
<p>In order to implement an automatically generated DAL based on Entity Framework today, you would have to use <a href="http://msdn.microsoft.com/en-us/library/bb387165.aspx" target="_blank">EdmGen</a>. Unfortunately, it does not give you access to some of the options supported by the framework. The new version of <a href="http://t4toolbox.codeplex.com/">T4 Toolbox</a> includes a code generator that encapsulates the functionality built into Entity Framework and makes it available in <a href="http://www.olegsych.com/2007/12/text-template-transformation-toolkit/" target="_blank">T4</a>-based code generation scripts. This code generator is based on the idea of using database modeling tools built into Visual Studio, which are easier to use and unlike Entity Framework’s own designer, are proven to work on the number of tables typically found in real-world databases. In the rest of this article we will review the process of using this code generator to illustrate its pros and cons.</p>
<h5>Getting Started</h5>
<p>In order to follow this sample, you need to have Visual Studio 2008 or 2010, Standard Edition or higher, SQL Server Express 2005 or later, <a href="http://t4toolbox.codeplex.com/">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>
<ul>
<li>Create a new C# or Visual Basic console application project. </li>
<li>Add a new item to your project and select the <em>Code Generation</em>-&gt;<em>Entity Framework Database</em> template in the <em>Add New Item </em>dialog. </li>
</ul>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Entity Framework Database template in the Add New Item Dialog" border="0" alt="Entity Framework Database template in the Add New Item Dialog" src="http://www.olegsych.com/wp-content/uploads/2009/12/image3.png" width="580" height="326" /></p>
<ul>
<li>Enter the desired database name and click <em>Add</em>. </li>
</ul>
<p>This template adds a new, empty SQL Express database to your project. Unfortunately, Visual Studio automatically displays the the Data Source Configuration Wizard whenever you add a .mdf file to a project. Normally, you would use it to create a data access layer with built-in visual designers. In this case, we have the entire data access layer generated automatically for us.</p>
<ul>
<li>Click <em>Cancel </em>in the <em>Data Source Configuration Wizard.</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="Data Source Configuration Wizard" border="0" alt="Data Source Configuration Wizard" src="http://www.olegsych.com/wp-content/uploads/2009/12/image4.png" width="580" height="486" /> <img style="border-right-width: 0px; margin: 5px 0px 5px 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Database and generated files in Solution Explorer" border="0" alt="Database and generated files in Solution Explorer" align="right" src="http://www.olegsych.com/wp-content/uploads/2009/12/image5.png" width="240" height="362" /></p>
<p>Notice that a number of files have been added to your project, including a .mdf file (SQL database), a .ldf file (SQL log), a .tt file (code generator), a .cs/.vb file (entity classes and object context), a .Views.cs/.vb file (precompiled entity views), a .csdl file (conceptual model), a .ssdl file (storage model) and a .msl file (mapping model). If you are using Visual Basic, you will need to click &quot;<em>Show All Files</em>” button in solution explorer in order to see the files nested under .mdf and .tt.</p>
<h5>Database Modeling</h5>
<p>Visual Studio includes a subset of database modeling functionality from SQL Server Management Studio, including database diagrams, table designers, key and relationship designers.</p>
<ul><img style="border-right-width: 0px; margin: 0px 40px 0px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Database in Server Explorer." border="0" alt="Database in Server Explorer." align="left" src="http://www.olegsych.com/wp-content/uploads/2009/12/image6.png" width="239" height="260" />
<li>Double-click the .mdf file in <em>Solution Explorer </em>(shown above)<em>.</em> This will cause the database to be opened in <em>Server Explorer</em> (shown on the left). </li>
<li>Right-click <em>Database Diagrams</em> in <em>Server Explorer</em> and select <em>Add New Diagram</em> from the context menu. </li>
<li>The first time you add a diagram to a database, Visual Studio will prompts you to create database objects required for diagramming. Click Yes when prompted. </li>
</ul>
<p>Use the diagram to create a new database model.</p>
<p><a href="http://www.olegsych.com/wp-content/uploads/2009/12/image7.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Database Diagram Toolbar" border="0" alt="Database Diagram Toolbar" src="http://www.olegsych.com/wp-content/uploads/2009/12/image-thumb3.png" width="580" height="22" /></a><a href="http://www.olegsych.com/wp-content/uploads/2009/12/image8.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Database Diagram Designer" border="0" alt="Database Diagram Designer" src="http://www.olegsych.com/wp-content/uploads/2009/12/image-thumb4.png" width="580" height="498" /></a></p>
<p><img style="border-right-width: 0px; margin: 0px 10px 0px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Use Properties Window to configure tables and columns." border="0" alt="Use Properties Window to configure tables and columns." align="left" src="http://www.olegsych.com/wp-content/uploads/2009/12/image9.png" width="240" height="301" />Database diagrams allow you to quickly model tables and their relationships. You can use the <em>Properties Window</em> of Visual Studio to configure individual tables and columns selected on the design surface. The toolbar and context menu provide access to commands that allow you to model keys, relationships, indexes, unique and check constraints, as well as customize the look of your diagram for display and print, add text annotations and more. Also, unlike with Entity Framework designer, you can create additional diagrams when the number of tables is too big to fit on a single diagram. This seemingly trivial feature is crucial for large database models.</p>
<p>Having the model database included in your project has several important benefits. It is placed under source control with the rest of the files in your project, giving you the ability to go back to previous versions when necessary. Although it may seem excessive to check in an entire database in source control, the size of a .mdf file is comparable to the size of a similar database model stored in a Visio .vsd file or an Enterprise Architect .eap file. You can also use the database file itself to store any seed data you need and with “Copy to Output Directory” option turned on, the database deployment becomes a simple xcopy on <a href="http://en.wikipedia.org/wiki/Greenfield_project" target="_blank">greenfield projects</a>.</p>
<ul>
<li>Make sure to save changes you make in any database diagram or designers you open before you proceed to the next step of generating code. </li>
</ul>
<h5>Code Generation</h5>
<ul>
<li>Double-click the .tt file in <em>Solution Explorer </em>(shown above) to open it in the <a href="http://www.olegsych.com/2009/04/t4-editor-by-tangible-engineering/">T4 Editor</a>. </li>
</ul>
<h6>C#</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">template</span><span style="color: #000000"> </span><span style="color: #ff0000">language</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">C#</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="color: #ff0000">hostspecific</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">True</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">output</span><span style="color: #000000"> </span><span style="color: #ff0000">extension</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">cs</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">include</span><span style="color: #000000"> </span><span style="color: #ff0000">file</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">T4Toolbox.tt</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">include</span><span style="color: #000000"> </span><span style="color: #ff0000">file</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">T4Toolbox\EntityFramework.tt</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#</span><span style="background-color: #ffffe0; color: #000000">
    <span style="background-color: #ffffe0; color: #0000ff">var</span> generator = </span><span style="background-color: #ffffe0; color: #0000ff">new</span><span style="background-color: #ffffe0; color: #000000"> EntityFrameworkGenerator();
    generator.DatabaseFile = </span><span style="background-color: #ffffe0; color: #800000">&quot;Database1.mdf&quot;</span><span style="background-color: #ffffe0; color: #000000">;
    generator.Run();
</span><span style="background-color: #ffd700; color: #000000">#&gt;</span></pre>
<h6>VB</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">template</span><span style="color: #000000"> </span><span style="color: #ff0000">language</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">VB</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="color: #ff0000">hostspecific</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">True</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">output</span><span style="color: #000000"> </span><span style="color: #ff0000">extension</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">vb</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">include</span><span style="color: #000000"> </span><span style="color: #ff0000">file</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">T4Toolbox.tt</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">include</span><span style="color: #000000"> </span><span style="color: #ff0000">file</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">T4Toolbox\EntityFramework.tt</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#</span><span style="background-color: #ffffe0; color: #000000">
    </span><span style="background-color: #ffffe0; color: #0000ff">Dim</span><span style="background-color: #ffffe0; color: #000000"> generator </span><span style="background-color: #ffffe0; color: #0000ff">As</span><span style="background-color: #ffffe0; color: #000000"> </span><span style="background-color: #ffffe0; color: #0000ff">New</span><span style="background-color: #ffffe0; color: #000000"> EntityFrameworkGenerator()
    generator.DatabaseFile = </span><span style="background-color: #ffffe0; color: #800000">&quot;Database1.mdf&quot;</span><span style="background-color: #ffffe0; color: #000000">
    generator.LanguageOption = LanguageOption.GenerateVBCode
    generator.Run()
</span><span style="background-color: #ffd700; color: #000000">#&gt;</span></pre>
<p>This is a <a href="http://www.olegsych.com/2007/12/text-template-transformation-toolkit/">T4</a> code generation script that creates a new instance of <em>EntityFrameworkGenerator</em>, configures its properties and uses it to generate all model and code files required for a ready-to-use data access layer based on Entity Framework. Note that this script is not directly associated with the database file in the Visual Studio project and has to be run manually.</p>
<ul>
<li>Right-click the .tt file in <em>Solution Explorer</em> and select <em>Run Custom Tool</em> from its context menu to trigger the code generation. </li>
<li>Double-click the&#160; generated .cs/.vb file in <em>Solution Explorer</em> to open it in the Visual Studio editor. If you are using Visual Basic, you will need to click “<em>Show All Files</em>” in the toolbar of <em>Solution Explorer</em> in order to see this file. </li>
</ul>
<h6>C#</h6>
<p><a href="http://www.olegsych.com/wp-content/uploads/2009/12/image10.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Generated C# Code" border="0" alt="Generated C# Code" src="http://www.olegsych.com/wp-content/uploads/2009/12/image-thumb5.png" width="580" height="456" /></a></p>
<h6>VB</h6>
<p><a href="http://www.olegsych.com/wp-content/uploads/2009/12/image11.png"><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/12/image-thumb6.png" width="580" height="477" /></a></p>
<p>This generated file contains definitions of both entity classes and object context required to access the database using LINQ to Entities.</p>
<p>Also note the other generated code file, in our example Database1.Views.cs/.vb. This file contains <a href="http://blogs.msdn.com/adonet/archive/2008/02/04/exploring-the-performance-of-the-ado-net-entity-framework-part-1.aspx" target="_blank">pre-generated views</a>, which significantly improve reduce the amount of time required to connect to a database using an Entity Framework object context for the first time. This can take tens of seconds even on a medium-size database with a hundred of tables. While this performance hit does not have a meaningful effect on applications in production due to Entity Framework caching the views on per-AppDomain basis, this delay is a significant problem for developers who need to recompile and restart the application frequently. The Entity Framework designer does not generate views automatically, causing much frustration for developers and, perhaps, being the main reason for Entity Frameworks reputation of having poor performance.</p>
<h5>Coding</h5>
<p>At this point, you have everything you need to start coding against your new database using LINQ to Entities.</p>
<ul>
<li>Double-click Program.cs or Module.vb in <em>Solution Explorer</em>. </li>
<li>Enter the following code in the editor. </li>
</ul>
<h6>C#</h6>
<pre class="code">
<span style="color: blue">using </span>System;
<span style="color: blue">using </span>System.Linq; 

<span style="color: blue">namespace </span>EfDalSampleCS
{
  <span style="color: blue">class </span><span style="color: #2b91af">Program
  </span>{
    <span style="color: blue">static void </span>Main(<span style="color: blue">string</span>[] args)
    {
      <span style="color: blue">var </span>context = <span style="color: blue">new </span><span style="color: #2b91af">Database1Entities</span>();
      context.AddToProducts(<span style="color: blue">new </span><span style="color: #2b91af">Product</span>() { ProductName = <span style="color: #a31515">&quot;Internet Explorer&quot;</span>, UnitPrice = <span style="color: brown">0 </span>});
      context.AddToProducts(<span style="color: blue">new </span><span style="color: #2b91af">Product</span>() { ProductName = <span style="color: #a31515">&quot;Windows 7 Ultimate&quot;</span>, UnitPrice = <span style="color: brown">319.99M </span>});
      context.SaveChanges(); 

      <span style="color: blue">var </span>products = <span style="color: blue">from </span>p <span style="color: blue">in </span>context.Products <span style="color: blue">select </span>p;
      <span style="color: blue">foreach </span>(<span style="color: blue">var </span>product <span style="color: blue">in </span>products)
      {
          <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">&quot;{0} ({1})&quot;</span>, product.ProductName, product.UnitPrice);
      }
    }
  }
}&#160; </pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<h6>VB</h6>
<pre class="code">
<span style="color: blue">Imports </span>System
<span style="color: blue">Imports </span>System.Linq
<span style="color: blue">Imports </span>EfDalSampleVB.EfDalSampleVB 

<span style="color: blue">Module </span><span style="color: #2b91af">Module1
    </span><span style="color: blue">Sub </span>Main()
        <span style="color: blue">Dim </span>context <span style="color: blue">As New </span><span style="color: #2b91af">Database1Entities
        </span>context.AddToProducts(<span style="color: blue">New </span><span style="color: #2b91af">Product</span>() <span style="color: blue">With </span>{.ProductName = <span style="color: #a31515">&quot;Internet Explorer&quot;</span>, .UnitPrice = <span style="color: brown">0</span>})
        context.AddToProducts(<span style="color: blue">New </span><span style="color: #2b91af">Product</span>() <span style="color: blue">With </span>{.ProductName = <span style="color: #a31515">&quot;Windows 7 Ultimate&quot;</span>, .UnitPrice = <span style="color: brown">319.99</span>})
        context.SaveChanges() 

        <span style="color: blue">Dim </span>products = <span style="color: blue">From </span>p <span style="color: blue">In </span>context.Products <span style="color: blue">Select </span>p
        <span style="color: blue">For Each </span>product <span style="color: blue">In </span>products
            <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">&quot;{0} ({1})&quot;</span>, product.ProductName, product.UnitPrice)
        <span style="color: blue">Next
    End Sub
End Module</span> 

<span style="color: blue"></span>&#160;</pre>
<p><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a></p>
<ul>
<li>Press F5 to run the program. You may want to set a breakpoint and observe execution of the program in Visual Studio debugger. </li>
</ul>
<p>A couple of things are worth explaining. How does this code know which database to connect to? The answer lies in the default constructor of <em>Database1Entities</em> class, which is generated to use a connection string with the same name. This connection string was automatically added to the configuration file when we added <em>Database1.mdf</em> to our project.</p>
<pre class="code"><span style="color: blue">&lt;?</span><span style="color: #a31515">xml </span><span style="color: red">version</span><span style="color: blue">=</span>&quot;<span style="color: blue">1.0</span>&quot; <span style="color: red">encoding</span><span style="color: blue">=</span>&quot;<span style="color: blue">utf-8</span>&quot;<span style="color: blue">?&gt;
&lt;</span><span style="color: #a31515">configuration</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">connectionStrings</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">add </span><span style="color: red">name</span><span style="color: blue">=</span>&quot;<span style="color: blue">Database1Entities</span>&quot;
      <span style="color: red">connectionString</span><span style="color: blue">=
      </span>&quot;
        <span style="color: blue">metadata=res://*/Database1.csdl
                |res://*/Database1.ssdl
                |res://*/Database1.msl;
        provider=System.Data.SqlClient;
        provider connection string=
        &#8216;
          Data Source=.\SQLEXPRESS;
          AttachDbFilename=|DataDirectory|\Database1.mdf;
          Integrated Security=True;
          User Instance=True
        &#8216;
      </span>&quot;
      <span style="color: red">providerName</span><span style="color: blue">=</span>&quot;<span style="color: blue">System.Data.EntityClient</span>&quot; <span style="color: blue">/&gt;
  &lt;/</span><span style="color: #a31515">connectionStrings</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">configuration</span><span style="color: blue">&gt;</span></pre>
<p><a href="http://www.olegsych.com/wp-content/uploads/2009/12/image12.png"><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="image" border="0" alt="image" align="right" src="http://www.olegsych.com/wp-content/uploads/2009/12/image-thumb7.png" width="226" height="240" /></a>Metadata section of the connection string specifies that .csdl, .ssdl and .msl files are embedded as resources in the executable. Provider section of the connection string instructs Entity Framework to use ADO.NET SQL Client to connect to the database. The provider connection string section contains the traditional connection string and indicates that SQL Server Express edition will be used to automatically attach the database file located in <em>DataDirectory</em>. For windows applications (such as the console app we have here), <em>DataDirectory</em> token refers to the directory where the&#160; executable is located. Our database file is copied to the output directory because the “Copy to Output Directory” option was set to “Copy Always” for the .mdf file in our project.</p>
<h5>Customizing the list of database objects exposed by DAL</h5>
<p>You may have noticed that among the generated entity classes, we also have <em>sysdiagrams</em>, which was actually the table created by SQL Server when we added the first diagram to our database. Unless you are planning to access this table from your application, it would be best to remove it from the data access layer. You can can do that by adding a <em>filter</em> to the code generator.</p>
<ul>
<li>Add the following code to the .tt file before <em>generator.Run()</em> method is called. </li>
</ul>
<h6>C#</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffffe0; color: #000000">  generator.Filters.Add(
    </span><span style="background-color: #ffffe0; color: #0000ff">new</span><span style="background-color: #ffffe0; color: #000000"> EntityStoreSchemaFilterEntry(
      </span><span style="background-color: #ffffe0; color: #0000ff">null</span><span style="background-color: #ffffe0; color: #000000">,   </span><span style="background-color: #ffffe0; color: #008000">// catalog</span><span style="background-color: #ffffe0; color: #000000">
      </span><span style="background-color: #ffffe0; color: #0000ff">null</span><span style="background-color: #ffffe0; color: #000000">,   </span><span style="background-color: #ffffe0; color: #008000">// schema</span><span style="background-color: #ffffe0; color: #000000">
      </span><span style="background-color: #ffffe0; color: #800000">&quot;sys%&quot;</span><span style="background-color: #ffffe0; color: #000000">, </span><span style="background-color: #ffffe0; color: #008000">// name</span><span style="background-color: #ffffe0; color: #000000">
      EntityStoreSchemaFilterObjectTypes.Table,
      EntityStoreSchemaFilterEffect.Exclude));</span></pre>
<h6>VB</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffffe0; color: #000000">  generator.Filters.Add( _
    </span><span style="background-color: #ffffe0; color: #0000ff">New</span><span style="background-color: #ffffe0; color: #000000"> EntityStoreSchemaFilterEntry( _
      </span><span style="background-color: #ffffe0; color: #0000ff">Nothing</span><span style="background-color: #ffffe0; color: #000000">, _
      </span><span style="background-color: #ffffe0; color: #0000ff">Nothing</span><span style="background-color: #ffffe0; color: #000000">, _
      </span><span style="background-color: #ffffe0; color: #800000">&quot;sys%&quot;</span><span style="background-color: #ffffe0; color: #000000">,  _
      EntityStoreSchemaFilterObjectTypes.Table, _
      EntityStoreSchemaFilterEffect.Exclude))</span></pre>
<p>This code creates a filter entry object that indicates that all tables whose name starts with <em>“sys”</em> should be excluded from the generated DAL. <em>EntityFrameworkGenerator</em> class contains a property called <em>Filters</em> to which you can add one or more filter entries and make sure that only appropriate database objects are accessible through the DAL. For complete details, please refer to <a href="http://msdn.microsoft.com/en-us/library/system.data.entity.design.entitystoreschemafilterentry.aspx" target="_blank">EntityStoreSchemaFilterEntry</a>, <a href="http://msdn.microsoft.com/en-us/library/system.data.entity.design.entitystoreschemafilterobjecttypes.aspx" target="_blank">EntityStoreSchemaFilterObjectTypes</a> and <a href="http://msdn.microsoft.com/en-us/library/system.data.entity.design.entitystoreschemafiltereffect.aspx" target="_blank">EntityStoreSchemaFilterEffect</a> on MSDN.</p>
<p>Unfortunately, not all of the possible combinations of object types and filter effects are supported by the underlying Entity Framework generator. For example, creating a filter entry to include functions in the DAL has no effect because the functions are only automatically generated in the storage model (.ssdl) and not in the conceptual model (.csdl). In other words, you cannot access stored procedures using the DAL produced by this code generator in its current version.</p>
<h5>Customizing pluralization of entity class names and set names</h5>
<p>Entity Framework 4.0 in Visual Studio 2010 provides an option to automatically convert table names to singular form in names of entity classes and to plural form in names of entity set properties. Without this automatic conversion, both entity name and set name would be either in plural form or singular form, depending on the naming convention you use in your database model. This poses a significant limitation in Entity Framework 3.5 in Visual Studio 2008, making the resulting DAL more confusing. A <a href="http://blogs.msdn.com/efdesign/archive/2008/12/02/pluralization.aspx" target="_blank">complete discussion of pluralization</a> by the Entity Framework team is available on their blog.</p>
<p>The code generator in T4 Toolbox has the pluralization turned on by default in Visual Studio 2010. If you need to generate the DAL without pluralization, perhaps for compatibility reasons, you can turn this option off by adding the following line to the .tt file before <em>generator.Run()</em> method is called.</p>
<h6>C#</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffffe0; color: #000000">  generator.Pluralize = </span><span style="background-color: #ffffe0; color: #0000ff">false</span><span style="background-color: #ffffe0; color: #000000">;</span></pre>
<h6>VB</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffffe0; color: #000000">  generator.Pluralize = </span><span style="background-color: #ffffe0; color: #0000ff">False</span></pre>
<p>This option is not available in Visual Studio 2008 because the underlying code generator in Entity Framework does not support it.</p>
<h5>Customizing generation of foreign key properties</h5>
<p>Entity Framework 4.0 in Visual Studio 2010 also provides an option to generate and use foreign key properties (such as Order.ProductId) in addition to navigation properties (such as Order.Product). Detailed discussion of <a href="http://blogs.msdn.com/efdesign/archive/2009/03/16/foreign-keys-in-the-entity-framework.aspx" target="_blank">foreign key properties</a> is also available on the Entity Framework team blog.</p>
<p>The code generator in T4 Toolbox offers an option to generate foreign key properties, however you need to turn it on explicitly, by adding the following line to the .tt file before <em>generator.Run()</em> method is called.</p>
<h6>C#</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffffe0; color: #000000">  generator.GenerateForeignKeyProperties = </span><span style="background-color: #ffffe0; color: #0000ff">true</span><span style="background-color: #ffffe0; color: #000000">;</span></pre>
<h6>VB</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffffe0; color: #000000">  generator.GenerateForeignKeyProperties = </span><span style="background-color: #ffffe0; color: #0000ff">True</span><span style="background-color: #ffffff; color: #000000"></span></pre>
<p>This option is not available in Visual Studio 2008 because the underlying code generator in Entity Framework does not support it.</p>
<h5>Customizing location of the model database</h5>
<p>When storing the model database under source control is not desirable on your project, you can change the code generator to use a standalone database as the model.</p>
<ul>
<li>Change the .tt file to specify a connection string instead of the database file. </li>
</ul>
<h6>C#</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">template</span><span style="color: #000000"> </span><span style="color: #ff0000">language</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">C#</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="color: #ff0000">hostspecific</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">True</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">output</span><span style="color: #000000"> </span><span style="color: #ff0000">extension</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">cs</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">include</span><span style="color: #000000"> </span><span style="color: #ff0000">file</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">T4Toolbox.tt</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">include</span><span style="color: #000000"> </span><span style="color: #ff0000">file</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">T4Toolbox\EntityFramework.tt</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#</span><span style="background-color: #ffffe0; color: #000000">
  EntityFrameworkGenerator generator = </span><span style="background-color: #ffffe0; color: #0000ff">new</span><span style="background-color: #ffffe0; color: #000000"> EntityFrameworkGenerator();
  generator.ConnectionString = </span><span style="background-color: #ffffe0; color: #800000">&quot;Server=.;Database=Northwind;Integrated Security=True&quot;</span><span style="background-color: #ffffe0; color: #000000">;
  generator.Run();
</span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span></pre>
<h6>VB</h6>
<pre style="background-color: white" class="code"><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">template</span><span style="color: #000000"> </span><span style="color: #ff0000">language</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">VB</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="color: #ff0000">hostspecific</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">True</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">output</span><span style="color: #000000"> </span><span style="color: #ff0000">extension</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">vb</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">include</span><span style="color: #000000"> </span><span style="color: #ff0000">file</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">T4Toolbox.tt</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#@</span><span style="color: #000000"> </span><span style="color: #a52a2a">include</span><span style="color: #000000"> </span><span style="color: #ff0000">file</span><span style="color: #000000">=</span><span style="color: #000000">&quot;</span><span style="color: #0000ff">T4Toolbox\EntityFramework.tt</span><span style="color: #000000">&quot;</span><span style="color: #000000"> </span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span><span style="background-color: #ffd700; color: #000000">&lt;#</span><span style="background-color: #ffffe0; color: #000000">
  </span><span style="background-color: #ffffe0; color: #0000ff">Dim</span><span style="background-color: #ffffe0; color: #000000"> generator </span><span style="background-color: #ffffe0; color: #0000ff">As</span><span style="background-color: #ffffe0; color: #000000"> </span><span style="background-color: #ffffe0; color: #0000ff">New</span><span style="background-color: #ffffe0; color: #000000"> EntityFrameworkGenerator()
  generator.ConnectionString = </span><span style="background-color: #ffffe0; color: #800000">&quot;Server=.;Database=Northwind;Integrated Security=True&quot;</span><span style="background-color: #ffffe0; color: #000000">
  generator.LanguageOption = LanguageOption.GenerateVBCode
</span><span style="background-color: #ffffe0; color: #000000">  generator.Run()
</span><span style="background-color: #ffd700; color: #000000">#&gt;</span><span style="color: #000000">
</span></pre>
<p>When you save the modified .tt file, the DAL will be regenerated based on the metadata in the database you specified in the connection string. By default, database name determines the name of the generated object context class. Changing the name of the database from <em>Database1</em> to <em>Northwind</em> will change the name of the context class from <em>Database1Entities </em>to <em>NorthwindEntities</em>.</p>
<ul>
<li>Rename the .tt file to match the name of the database (<em>Northwind.tt</em> in our example)<em>.</em> </li>
</ul>
<p>Although this is not required, renaming the code generation script will make the names of the generated .csdl, .ssdl and .msl files match the name of the database and make the solution easier to understand.</p>
<ul>
<li>Update the configuration file to match the changes made in generated code. </li>
</ul>
<pre class="code"><span style="color: blue">&lt;?</span><span style="color: #a31515">xml </span><span style="color: red">version</span><span style="color: blue">=</span>&quot;<span style="color: blue">1.0</span>&quot; <span style="color: red">encoding</span><span style="color: blue">=</span>&quot;<span style="color: blue">utf-8</span>&quot;<span style="color: blue">?&gt;
&lt;</span><span style="color: #a31515">configuration</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">connectionStrings</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">add </span><span style="color: red">name</span><span style="color: blue">=</span>&quot;<span style="color: blue">NorthwindEntities</span>&quot;
      <span style="color: red">connectionString</span><span style="color: blue">=
      </span>&quot;
        <span style="color: blue">metadata=res://*/Northwind.csdl
                |res://*/Northwind.ssdl
                |res://*/Northwind.msl;
        provider=System.Data.SqlClient;
        provider connection string=
        &#8216;
          Server=.;
          Database=Northwind;
          Integrated Security=True;
        &#8216;
      </span>&quot;
      <span style="color: red">providerName</span><span style="color: blue">=</span>&quot;<span style="color: blue">System.Data.EntityClient</span>&quot; <span style="color: blue">/&gt;
  &lt;/</span><span style="color: #a31515">connectionStrings</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">configuration</span><span style="color: blue">&gt;</span></pre>
<p>In particular, the name of the connection string has to match the new name of the object context class (<em>NorthwindEntities</em> in this example); file names in the metadata section of the connection string have to match the names of the generated model files (<em>Northwind.csdl</em>, <em>Northwind.ssdl </em>and <em>Northwind.msl</em> in this example); and finally, the provider connection string section of the connection string has to point to the actual database in your current environment.</p>
<p>Note that database connection string is present in both .tt and .config files. In this example, the same Northwind database on local SQL server is used during both code generation and execution. You may want to use different databases for these purposes, perhaps an empty local database for code generation and a shared database for development and testing. In that case, make sure to use appropriate connection strings in the .tt and .config files.</p>
<h5>Other customization options</h5>
<p>Additional details about customization options are available in the T4 Toolbox documentation installed as part of the Visual Studio 2008 help collection. If you have it installed, you can click <a href="ms-help://MS.VSCC.v90/MS.VSIPCC.v90/T4Toolbox/T4Toolbox/html/AllMembers_T_T4Toolbox_EntityFramework_EntityFrameworkGenerator.htm" target="_blank">here</a> to open the list of properties available for you to use in the code generation script.</p>
<h4>Conclusion</h4>
<p>ADO.NET Entity Framework allows you to access database in object-oriented manner at the cost of additional effort required to maintain conceptual, storage and mapping model. While sounding good in theory, solving the object-relational impedance mismatch in practice typically increases the cost of information systems due to additional knowledge, experience and effort it requires with tools available today. By implementing an automatically-generated, modern, strongly-typed, LINQ-enabled data access layer based on Entity Framework, we can improve developer productivity and reduce the system development cost without introducing the overhead and complexity of fully featured object-relational mapping. Unlike the tools built into Entity Framework, the database modeling functionality in Visual Studio and the code generator described in this article allow you to use Entity Framework effectively with more than just a few dozen tables. Unfortunately, due to limitations in the current version of Entity Framework, the solution described in this article does not allow accessing stored procedures and functions through the automatically generated DAL, making it inferior compared to a similar DAL based on LINQ to SQL today.</p>
<h5><strong>Download</strong></h5>
<p><a href="http://www.olegsych.com/wp-content/uploads/2009/12/efdalsample.zip">Sample source code</a></p>
<p>&copy;2012 <a href="http://www.olegsych.com">Oleg Sych</a>. All Rights Reserved.</p>.<img src="http://feeds.feedburner.com/~r/olegsych/~4/VPIPHzeX4Xg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.olegsych.com/2009/12/simplifying-entity-framework-data-driven-design/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>

