<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	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:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Sam Beauvois &#187; T4</title>
	<atom:link href="http://www.sambeauvois.be/blog/tag/t4/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.sambeauvois.be/blog</link>
	<description>general dev, .net and other stuff</description>
	<lastBuildDate>Tue, 31 Jan 2012 13:38:32 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1</generator>
		<item>
		<title>I want my foreign key to be mapped to a single object and not a collection</title>
		<link>http://www.sambeauvois.be/blog/2010/06/i-want-my-foreign-key-to-be-mapped-to-a-single-object-and-not-a-collection/</link>
		<comments>http://www.sambeauvois.be/blog/2010/06/i-want-my-foreign-key-to-be-mapped-to-a-single-object-and-not-a-collection/#comments</comments>
		<pubDate>Tue, 15 Jun 2010 09:57:16 +0000</pubDate>
		<dc:creator>Sam Beauvois</dc:creator>
				<category><![CDATA[SubSonic]]></category>
		<category><![CDATA[Code generation]]></category>
		<category><![CDATA[T4]]></category>

		<guid isPermaLink="false">http://www.sambeauvois.be/blog/?p=470</guid>
		<description><![CDATA[Say you have two tables:  Teams and Registrations Registration has a foreign key for Teams : In Subsonic 3, the Registration class will have a property called “Beach_Teams” which returns a IQueryable&#60;Beach_Team&#62; collection. If we look at the generate class in the activerecord.cs file, there is a “Foreign Keys” region which contains the Beach_Teams property: [...]]]></description>
			<content:encoded><![CDATA[<p>Say you have two tables:  Teams and Registrations</p>
<p>Registration has a foreign key for Teams :</p>
<p><a href="http://www.sambeauvois.be/blog/wp-content/uploads/2010/06/image.png" target="_blank"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" src="http://www.sambeauvois.be/blog/wp-content/uploads/2010/06/image_thumb.png" border="0" alt="image" width="484" height="218" /></a></p>
<p>In Subsonic 3, the Registration class will have a property called “Beach_Teams” which returns a IQueryable&lt;Beach_Team&gt; collection.</p>
<p>If we look at the generate class in the activerecord.cs file, there is a “Foreign Keys” region which contains the Beach_Teams property:</p>
<pre class="brush: csharp; title: ;">

 #region ' Foreign Keys '
 public IQueryable&lt;Beach_Team&gt; Beach_Teams
 {
   get
   {
     var repo=LJR.DAL.Activities.Beach.Beach_Team.GetRepo();
     return from items in repo.GetAll()
          where items.TeamID == _TeamIDfk
          select items;
   }
 }

#endregion
</pre>
<p>It’s not ok for my use, I want a property returning only one &#8220;Beach_Team” object, so I can use it in my presentation layer with databound controls with no efforts</p>
<pre class="brush: xml; title: ;">
&lt;asp:ListView runat=&quot;server&quot; ID=&quot;LastTeams&quot; DataSourceID=&quot;registrationsOds&quot;&gt;
   &lt;ItemTemplate&gt;
     &lt;%# Eval(&quot;Beach_Team.Name&quot;)%&gt;
   &lt;/ItemTemplate&gt;
 &lt;/asp:ListView&gt;
</pre>
<p>So, what can I do ?</p>
<p>I can edit the ActiveRecord.cs file and add a property called “Beach_Team” and returning a Beach_Team object</p>
<pre class="brush: csharp; title: ;">
 public Beach_Team Beach_Team
 {
   get
   {
     var repo = LJR.DAL.Activities.Beach.Beach_Team.GetRepo();
    return repo.GetByKey(_TeamIDfk);
   }
 }
</pre>
<p>It do the job !</p>
<p>But if I want to regenerate the ActiveRecord.cs file, my modification will be lost !</p>
<p>So the good solution is to modify the T4 template to generate this property.</p>
<p>Let’s do this :</p>
<p>Go to the ActiveRecord.tt file and search for &#8216; Foreign Keys &#8216;.</p>
<p>Once you have find it look how it works:</p>
<pre class="brush: csharp; title: ;">

#region ' Foreign Keys '
&lt;#
 List&lt;string&gt; fkCreated = new List&lt;string&gt;();
 foreach(FKTable fk in tbl.FKTables)
 {
   if(IsTableOkToBeIncluded(fk.OtherTable))
   {
    string propName=fk.OtherQueryable;
    if(fkCreated.Contains(propName))
    {
      propName=fk.OtherQueryable+fkCreated.Count.ToString();
    }
    fkCreated.Add(fk.OtherQueryable);
#&gt;
   public IQueryable&lt;&lt;#=fk.OtherClass #&gt;&gt; &lt;#=propName #&gt;
  {
  get
  {
     var repo=&lt;#=Namespace #&gt;.&lt;#=fk.OtherClass#&gt;.GetRepo();
     return from items in repo.GetAll()
         where items.&lt;#=CleanUp(fk.OtherColumn)#&gt; == _&lt;#=CleanUp(fk.ThisColumn)#&gt;
         select items;
   }
 }

&lt;#
 }
 }
#&gt;
 #endregion
</pre>
<p>In a nutshell, for each tables linked to the table we are on, we check if the access code to the table has to be generated (see my previous article : <a href="http://www.sambeauvois.be/blog/2010/06/subsonic-specify-the-tables-you-really-need/" target="_blank">Subsonic : Specify the tables you really need !</a> ).</p>
<p>If the code has to be generated, we create a string variable named “propName” which will be the name of the property.</p>
<p>If this property already exists, we suffix the name to be sure we don&#8217;t have the same property twice.</p>
<p>Then we generate the IQueryable property.</p>
<p>Now, the first thing we want is to have the property name equals to the object name.</p>
<p>We could think that we don’t have to twist our minds because  we already have it with “fk.OtherClass” and i could be like that</p>
<pre class="brush: csharp; title: ;">
 public &lt;#=fk.OtherClass #&gt; &lt;#=fk.OtherClass #&gt;
 {
  get
  {
   var repo=&lt;#=Namespace #&gt;.&lt;#=fk.OtherClass#&gt;.GetRepo();
   return repo.GetByKey(_&lt;#=CleanUp(fk.ThisColumn)#&gt;);
  }
 }
</pre>
<p>But what if we have two foreign keys to the same table ? We will have the same property twice! and we have to avoid it!</p>
<p>So, we have to check if this property isn’t already generated.</p>
<p>To do this, we can use the list “fkCreated” already present in the code, and create a “secondPropName” string variable, assign it the value of the OtherClass and check if it’s not already created :</p>
<pre class="brush: csharp; title: ;">
 string secondPropName=fk.OtherClass;
 if(fkCreated.Contains(secondPropName))
 {
   secondPropName+=fkCreated.Count.ToString();
 }
 fkCreated.Add(secondPropName);
</pre>
<p>There is the final code</p>
<pre class="brush: csharp; title: ;">

#region ' Foreign Keys '
&lt;#
 List&lt;string&gt; fkCreated = new List&lt;string&gt;();
 foreach(FKTable fk in tbl.FKTables)
 {
   if(IsTableOkToBeIncluded(fk.OtherTable))
   {
    string propName=fk.OtherQueryable;
    if(fkCreated.Contains(propName))
    {
     propName=fk.OtherQueryable+fkCreated.Count.ToString();
    }
   fkCreated.Add(fk.OtherQueryable);

   string secondPropName=fk.OtherClass;
   if(fkCreated.Contains(secondPropName))
   {
     secondPropName+=fkCreated.Count.ToString();
   }
   fkCreated.Add(secondPropName);
#&gt;
  public IQueryable&lt;&lt;#=fk.OtherClass #&gt;&gt; &lt;#=propName #&gt;
  {
    get
    {
      var repo=&lt;#=Namespace #&gt;.&lt;#=fk.OtherClass#&gt;.GetRepo();
      return from items in repo.GetAll()
        where items.&lt;#=CleanUp(fk.OtherColumn)#&gt; == _&lt;#=CleanUp(fk.ThisColumn)#&gt;
        select items;
    }
  }

  public &lt;#=fk.OtherClass #&gt; &lt;#=secondPropName #&gt;
  {
    get
    {
      var repo=&lt;#=Namespace #&gt;.&lt;#=fk.OtherClass#&gt;.GetRepo();
      return repo.GetByKey(_&lt;#=CleanUp(fk.ThisColumn)#&gt;);
    }
  }

&lt;#
 }
 }
#&gt;
 #endregion
</pre>
<p>Now I can use the linked object directly !</p>
<p>You can donwload my T4 templates <a href="http://www.sambeauvois.be/Demos/SubSonic/FKasSingleObject/20100615ActiveRecord.zip" target="_blank">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sambeauvois.be/blog/2010/06/i-want-my-foreign-key-to-be-mapped-to-a-single-object-and-not-a-collection/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Subsonic : Specify the tables you really need !</title>
		<link>http://www.sambeauvois.be/blog/2010/06/subsonic-specify-the-tables-you-really-need/</link>
		<comments>http://www.sambeauvois.be/blog/2010/06/subsonic-specify-the-tables-you-really-need/#comments</comments>
		<pubDate>Mon, 14 Jun 2010 13:11:02 +0000</pubDate>
		<dc:creator>Sam Beauvois</dc:creator>
				<category><![CDATA[SubSonic]]></category>
		<category><![CDATA[Code generation]]></category>
		<category><![CDATA[T4]]></category>

		<guid isPermaLink="false">http://www.sambeauvois.be/blog/?p=435</guid>
		<description><![CDATA[With the Subsonic&#8217;s T4 Templates you can specify the tables you don&#8217;t want the access code to be generated. But what if you want to choose the tables for which the mapping classes will be created ? Actually you can have many reasons to do that : having an application using only specific tables from [...]]]></description>
			<content:encoded><![CDATA[<p>With the Subsonic&#8217;s T4 Templates you can specify the tables you don&#8217;t want the access code to be generated.</p>
<p>But what if you want to choose the tables for which the mapping classes will be created ?</p>
<p>Actually you can have many reasons to do that : having an application using only specific tables from a big system or having the ability to separate distinct parts of a system by example.</p>
<p>In my case I wanted to use only three tables from my database to build an ASP.NET membership provider. This is the example I&#8217;ll use for this article.</p>
<p style="text-align: left;">So, in my database I have at least three tables :</p>
<ul>
<li>Users</li>
<li>Roles</li>
<li>UsersInRoles</li>
</ul>
<p>Now I want to generate the DAL layer only for these tables, so I create a new code library project, a add an app.config file containing the connection string and add the Subsonic.Core reference.</p>
<p>The I have to add my T4 template, but they are not ready. I have to modify them to allow the selection of my tables.</p>
<p>To do that, I go to the T4 template directory and edit the &#8220;Settings.ttinclude&#8221; and the &#8220;Context.tt&#8221; files :</p>
<p style="text-align: left;"><a href="http://www.sambeauvois.be/blog/wp-content/uploads/2010/06/T4TemplatesDirectory.png"><img class="aligncenter size-medium wp-image-442" title="T4TemplatesDirectory" src="http://www.sambeauvois.be/blog/wp-content/uploads/2010/06/T4TemplatesDirectory-480x249.png" alt="T4TemplatesDirectory" width="480" height="249" /></a></p>
<p>First, check how it works</p>
<p>In the &#8220;Settings.ttinclude&#8221; file, line #30 we see the definition of the tables to be excluded:</p>
<pre class="brush: csharp; title: ;">

//this is a list of tables you don't want generated
string[] ExcludeTables = new string[]{
&quot;sysdiagrams&quot;,
&quot;BuildVersion&quot;
};
</pre>
<p>In the &#8220;Context.tt&#8221; file, il we search for &#8220;ExcludeTables&#8221;, we find three part of code using it in the same way:</p>
<pre class="brush: csharp; title: ;">
// line 135

&lt;#  foreach(Table tbl in tables){
if(!ExcludeTables.Contains(tbl.Name))
{

// ...

// line 251

foreach(Table tbl in tables)
{
if(!ExcludeTables.Contains(tbl.Name))
{

// ...

// line 271

foreach(Table tbl in tables)
{
if(!ExcludeTables.Contains(tbl.Name))
{

// ....
</pre>
<p>Now that we know how it&#8217;s working, we can modify the T4 templates to add the ability to choose the tables we want</p>
<p>The simplest option would be to replace the &#8220;ExcludeTables&#8221; array by &#8220;IncludeTables&#8221; and to remove the logical NOT operator (!) in the conditions and the job will be done.</p>
<p>But if we think a bit, we realize that there is many ways to choose the tables we want.<br />
We can decide to choose :</p>
<ul>
<li>All tables</li>
<li>All tables except the specified ones</li>
<li>Only the specified tables</li>
<li>All tables matching a pattern (example : starting by &#8220;MyApplication_&#8221;)</li>
<li>An other choice method</li>
</ul>
<h3>My solution :</h3>
<h4>In the &#8220;Settings.ttinclude&#8221; file:</h4>
<p>Add a string array named &#8220;IncludeTables&#8221; containing the tables you want :</p>
<pre class="brush: csharp; title: ;">

// this is the list of the tables you want to be generated
string[] IncludeTables = new string[]{
&quot;Users&quot;,
&quot;Roles&quot;,
&quot;UsersInRoles&quot;
};
</pre>
<p>Add a string variable named TablePrefix</p>
<pre class="brush: csharp; title: ;">
 // the prefix of the table you want to be generated
 string TablePrefix=&quot;&quot;;
</pre>
<p>Add an enumeration named &#8220;TableChoiceMethod&#8221; and containing the different ways to choose the tables:</p>
<pre class="brush: csharp; title: ;">

enum TableChoiceMethod
 {
SpecifiedExcludes,
SpecifiedIncludes,
SpecifiedPrefix,
All
 }
</pre>
<p>Add a variable for this enum, set to the value you want</p>
<pre class="brush: csharp; title: ;">

// define the table choice method
 TableChoiceMethod tableChoiceMethod = TableChoiceMethod.SpecifiedIncludes;
</pre>
<p>Create  a &#8220;“IsTableOkToBeIncluded&#8221; method taking care of the choice we made in the activerecord file and returning whether or not the table is ok to be generated.</p>
<pre class="brush: csharp; title: ;">

bool IsTableOkToBeIncluded(string tableName)
{
 switch(tableChoiceMethod)
 {
  case TableChoiceMethod.SpecifiedIncludes:
  {
   return IncludeTables.Contains(tableName);
  }
  case TableChoiceMethod.SpecifiedExcludes:
  {
   return !ExcludeTables.Contains(tableName);
  }
  case TableChoiceMethod.SpecifiedPrefix:
  {
  return tableName.StartsWith(TablePrefix, StringComparison.InvariantCultureIgnoreCase);
  }
  default: // assume TableChoiceMethod.All
  {
   return true;
  }
 }
}
</pre>
<h4>In the Context.tt, ActiveRecord.tt and Struct.tt files :</h4>
<p>Replace the condition&#8221;if(!ExcludeTables.Contains(tbl.Name))&#8221; by this method</p>
<pre class="brush: csharp; title: ;">

&lt;#  foreach(Table tbl in tables){
if(IsTableOkToBeIncluded(tbl.Name))
{

// ...
</pre>
<p>Now specify the Namespace, ConnectionStringName and DatabaseName in the Settings.ttinclude file.</p>
<p>Add the template to your DAL project,</p>
<p>Generate</p>
<p>You are done !</p>
<p>You can download my templates <a href="http://www.sambeauvois.be/Demos/SubSonic/ChooseTables/20100614ActiveRecord.zip" target="_blank">here</a>.</p>
<h4>Remarks :</h4>
<ul>
<li>The Subsonic version I use is 3.0.0.4.</li>
<li>I&#8217;m running Windows 7 64 bits and I had  unblock the files in windows explorer.</li>
<li>I had to run Visual Studio as an administrator.</li>
<li>If you are not familiar with subsonic, I invite you to watch the <a href="http://subsonicproject.com/docs/The_5_Minute_Demo" target="_blank">5 minute demo</a> and read the <a href="http://subsonicproject.com/docs/Using_ActiveRecord" target="_blank">startup  tutorial</a> from the <a href="http://subsonicproject.com/" target="_blank">subsonicproject </a>website.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.sambeauvois.be/blog/2010/06/subsonic-specify-the-tables-you-really-need/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

