<?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; SubSonic</title>
	<atom:link href="http://www.sambeauvois.be/blog/category/subsonic/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>Bring a bit of the Subsonic power to Entity Framework by adding automatic audit and logical delete fields</title>
		<link>http://www.sambeauvois.be/blog/2011/11/bring-a-bit-of-the-subsonic-power-to-entity-framework-by-adding-automatic-audit-and-logical-delete-fields/</link>
		<comments>http://www.sambeauvois.be/blog/2011/11/bring-a-bit-of-the-subsonic-power-to-entity-framework-by-adding-automatic-audit-and-logical-delete-fields/#comments</comments>
		<pubDate>Fri, 04 Nov 2011 16:04:07 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[ADO.NET]]></category>
		<category><![CDATA[Productivity]]></category>
		<category><![CDATA[SubSonic]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.sambeauvois.be/blog/?p=915</guid>
		<description><![CDATA[Here is the code to do the same thing than in my previous article &#8220;Bring a bit of the Subsonic power to Linq to sql by adding automatic audit and logical delete fields&#8221; namespace YouNamespace.DAL { using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Data; using System.Data.Common; using System.Data.Objects; using System.Linq; public partial class [...]]]></description>
			<content:encoded><![CDATA[<p>Here is the code to do the same thing than in my previous article <a href="http://www.sambeauvois.be/blog/2010/09/bring-a-bit-of-the-subsonic-power-to-linq-to-sql-by-adding-automatic-audit-and-logical-delete-fields/" target="_blank">&#8220;Bring a bit of the Subsonic power to Linq to sql by adding automatic audit and logical delete fields&#8221;</a></p>
<pre class="brush: csharp; title: ;">

namespace YouNamespace.DAL
{
 using System;
 using System.Collections;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
 using System.Data;
 using System.Data.Common;
 using System.Data.Objects;
 using System.Linq;

 public partial class YOURCONTEXTEntities
 {
 /// &lt;summary&gt;
 /// System fields for automatic audit and logical delete
 /// &lt;/summary&gt;
 private struct SystemFields
 {
 public const string CreatedOn = &quot;CREATEDON&quot;;
 public const string ModifiedOn = &quot;MODIFIEDON&quot;;
 public const string CreatedBy = &quot;CREATEDBY&quot;;
 public const string ModifiedBy = &quot;MODIFIEDBY&quot;;
 public const string IsDeleted = &quot;ISDELETED&quot;;
 }

 /// &lt;summary&gt;
 /// Overriding the SaveChanges method to automaticaly set system fields if any.
 /// &lt;/summary&gt;
 /// &lt;param name=&quot;options&quot;&gt;&lt;/param&gt;
 /// &lt;returns&gt;&lt;/returns&gt;
 public override int SaveChanges(System.Data.Objects.SaveOptions options)
 {
 IEnumerable&lt;ObjectStateEntry&gt; newEntries = this.ObjectStateManager.GetObjectStateEntries(EntityState.Added);

 foreach (ObjectStateEntry entry in newEntries)
 {
 ReadOnlyCollection&lt;FieldMetadata&gt; fieldsMetaData = entry.CurrentValues
 .DataRecordInfo.FieldMetadata;

 FieldMetadata createdOnField = fieldsMetaData
 .Where(f =&gt; string.Equals(f.FieldType.Name, SystemFields.CreatedOn, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();

 if (createdOnField.FieldType != null)
 {
 entry.CurrentValues.SetValue(createdOnField.Ordinal, DateTime.Now);
 }

 FieldMetadata createdByField = fieldsMetaData
 .Where(f =&gt; string.Equals(f.FieldType.Name, SystemFields.CreatedBy, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();

 if (createdByField.FieldType != null)
 {
 entry.CurrentValues.SetValue(createdByField.Ordinal, &quot;Sam&quot;);
 }

 FieldMetadata deletedField = fieldsMetaData
 .Where(f =&gt; string.Equals(f.FieldType.Name, SystemFields.IsDeleted, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();

 if (deletedField.FieldType != null)
 {
 entry.CurrentValues.SetValue(deletedField.Ordinal, false);
 }
 }

 IEnumerable&lt;ObjectStateEntry&gt; modifiedEntries = this.ObjectStateManager.GetObjectStateEntries(EntityState.Modified);
 foreach (ObjectStateEntry entry in modifiedEntries)
 {
 ReadOnlyCollection&lt;FieldMetadata&gt; fieldsMetaData = entry.CurrentValues
 .DataRecordInfo.FieldMetadata;

 FieldMetadata createdOnField = fieldsMetaData
 .Where(f =&gt; string.Equals(f.FieldType.Name, SystemFields.ModifiedOn, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();

 if (createdOnField.FieldType != null)
 {
 entry.CurrentValues.SetValue(createdOnField.Ordinal, DateTime.Now);
 }

 FieldMetadata createdByField = fieldsMetaData
 .Where(f =&gt; string.Equals(f.FieldType.Name, SystemFields.ModifiedBy, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();

 if (createdByField.FieldType != null)
 {
 entry.CurrentValues.SetValue(createdByField.Ordinal, &quot;Sam&quot;);
 }
 }

 IEnumerable&lt;ObjectStateEntry&gt; deletedEntries = this.ObjectStateManager.GetObjectStateEntries(EntityState.Deleted);
 foreach (ObjectStateEntry entry in deletedEntries)
 {
 // change from deleted to modified (!important)
 this.ObjectStateManager.ChangeObjectState(entry.Entity, EntityState.Modified);

 ReadOnlyCollection&lt;FieldMetadata&gt; fieldsMetaData = entry.CurrentValues
 .DataRecordInfo.FieldMetadata;

 FieldMetadata deletedField = fieldsMetaData
 .Where(f =&gt; string.Equals(f.FieldType.Name, SystemFields.IsDeleted, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();

 if (deletedField.FieldType != null)
 {
 entry.CurrentValues.SetValue(deletedField.Ordinal, true);
 }
else
 {
 // change back from modified to deleted (!important)
 this.ObjectStateManager.ChangeObjectState(entry.Entity, EntityState.Deleted);
 }
 }

 return base.SaveChanges(options);
 }
 }
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.sambeauvois.be/blog/2011/11/bring-a-bit-of-the-subsonic-power-to-entity-framework-by-adding-automatic-audit-and-logical-delete-fields/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Bring a bit of the Subsonic power to Linq to sql by adding automatic audit and logical delete fields</title>
		<link>http://www.sambeauvois.be/blog/2010/09/bring-a-bit-of-the-subsonic-power-to-linq-to-sql-by-adding-automatic-audit-and-logical-delete-fields/</link>
		<comments>http://www.sambeauvois.be/blog/2010/09/bring-a-bit-of-the-subsonic-power-to-linq-to-sql-by-adding-automatic-audit-and-logical-delete-fields/#comments</comments>
		<pubDate>Tue, 14 Sep 2010 07:08:36 +0000</pubDate>
		<dc:creator>Sam Beauvois</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Linq]]></category>
		<category><![CDATA[SubSonic]]></category>

		<guid isPermaLink="false">http://www.sambeauvois.be/blog/?p=532</guid>
		<description><![CDATA[[Update] You cand find the code to do the same with entity framework here [/Update] Recently I had to work on a project using Linq to sql  and I was suprised to see that Linq to SQL has no built-in auditing ability. There is no support for logical deletion neither. With the SubSonic&#8217;s ActiveReccord, all [...]]]></description>
			<content:encoded><![CDATA[<p>[Update]<br />
You cand find the code to do the same with entity framework <a href="http://www.sambeauvois.be/blog/2011/11/bring-a-bit-of-the-subsonic-power-to-entity-framework-by-adding-automatic-audit-and-logical-delete-fields/" target="_blank">here</a><br />
[/Update]</p>
<p>Recently I had to work on a project using Linq to sql  and I was suprised to see that Linq to SQL has no built-in auditing ability.</p>
<p>There is no support for logical deletion neither.</p>
<p>With the SubSonic&#8217;s ActiveReccord, all these features are built in (see the <a href="http://subsonicproject.com/docs/Conventions" target="_blank">documentation page</a>).</p>
<p>So, I decided to add this ability for the project, because I doesn&#8217;t want to change all the existing request to add these informations.</p>
<p>In my BLL layer, I have a manager object for my DAL Linq objects, so by Example if I have an &#8220;User&#8221; Object in my DAL layer, I have an &#8220;UserManager&#8221; object in my BLL layer.</p>
<p>All my managers objects inherit a &#8220;ManagerBase&#8221; Object, which contains only a &#8220;DataContext&#8221; Property, which can be used in the child classes.</p>
<p>So my first approach was to add a “SubmitChanges”  method in that class and call it from my child classes instead of directly call the one from the DataContext.</p>
<p>In my SubmitChanges method I add the needed logic before calling the one from the DataContext.</p>
<p>But I realized that when there are more than one developper working on an application, it can be difficult to ensure that everybody use the same technique. A person may not use the base class, another may forget to use the base class method, or other things..</p>
<p>Then I investigated the DataContext object with <a href="http://www.red-gate.com/products/reflector/" target="_blank">Reflector</a>, and I noticed that the SubmitChanges(void) method directly call the SubmitChanges(ConflictMode) one</p>
<pre class="brush: csharp; title: ;">

public void SubmitChanges()
{
 this.CheckDispose();
 this.SubmitChanges(ConflictMode.FailOnFirstConflict);
}
</pre>
<p>And if I take a look at the generated DataContext, I see that the DataContext is a partial class</p>
<pre class="brush: csharp; title: ;">

public partial class MyContext: System.Data.Linq.DataContext
{
 // ...
}
</pre>
<p>So, I decided to add a new file in my DAL layer and extend the DataContext</p>
<pre class="brush: csharp; title: ;">
partial class MyContext
{
// ...
}
</pre>
<p>Then override the SubmitChanges(ConflictMode) DataContext method</p>
<pre class="brush: csharp; title: ;">

public override void SubmitChanges(System.Data.Linq.ConflictMode failureMode)
 {
SetSystemFields(); // notice this method call !
base.SubmitChanges(failureMode);
 }
</pre>
<p>In the SetSystemFields method, I retrieve the pending changes</p>
<pre class="brush: csharp; title: ;">

private void SetSystemFields()
 {
ChangeSet changeset = this.GetChangeSet();

// ...
}
</pre>
<p>Then I retrieve the user identity in order to be able to set the CreatedBy and ModifiedBy properties of my data objects</p>
<pre class="brush: csharp; title: ;">

System.Security.Principal.WindowsIdentity identity = System.Security.Principal.WindowsIdentity.GetCurrent();
 string userName = &quot;Unknow&quot;;
 if (identity != null)
 {
userName = identity.Name;
 }
</pre>
<p>Then I loop over the objects that have to be inserted</p>
<pre class="brush: csharp; title: ;">

int maxInserts = changeset.Inserts.Count;
for (int i = 0; i &lt; maxInserts; i++)
{

// ...

}
</pre>
<p>and I use reflection to get the audit properties and set their values</p>
<pre class="brush: csharp; title: ;">

object entity = changeset.Inserts[i];
 Type objectType = entity.GetType();
 PropertyInfo[] properties = objectType.GetProperties();

foreach (PropertyInfo property in properties)
 {
switch (property.Name.ToUpper())
{
case SystemFields.CreatedOn:
case SystemFields.ModifiedOn:
{
property.SetValue(entity, DateTime.Now, null);
} break;
case SystemFields.CreatedBy:
case SystemFields.ModifiedBy:
{
property.SetValue(entity, userName, null);
} break;
case SystemFields.IsDeleted:
{
property.SetValue(entity, false, null);
} break;
default:
break;
}
 }
</pre>
<p>Remark : &#8220;SystemFields&#8221; is a struct I defined with the audit column names but you may as well make it come from a config file.</p>
<pre class="brush: csharp; title: ;">

private struct SystemFields
{
 public const string CreatedOn = &quot;CREATEDON&quot;;
 public const string ModifiedOn = &quot;MODIFIEDON&quot;;
 public const string CreatedBy = &quot;CREATEDBY&quot;;
 public const string ModifiedBy = &quot;MODIFIEDBY&quot;;
 public const string IsDeleted = &quot;ISDELETED&quot;;
}
</pre>
<p>I do the same treatment for the update and deletes (if I want to enable them).</p>
<p>Now everytime that the DataContext&#8217;s SubmitChanges method is called, the audit fields are automaticaly set!</p>
<p>Here is the full partial class for the DataContext</p>
<pre class="brush: csharp; title: ;">
using System;
using System.Data.Linq;
using System.Reflection;

namespace MyNamespace.DAL
{
 partial class MyContext
 {
  /// &lt;summary&gt;
  /// system fields for automatic audit and logical delete
  /// &lt;/summary&gt;
  private struct SystemFields
   {
        public const string CreatedOn = &quot;CREATEDON&quot;;
        public const string ModifiedOn = &quot;MODIFIEDON&quot;;
        public const string CreatedBy = &quot;CREATEDBY&quot;;
        public const string ModifiedBy = &quot;MODIFIEDBY&quot;;
        public const string IsDeleted = &quot;ISDELETED&quot;;
  }

public override void SubmitChanges(System.Data.Linq.ConflictMode failureMode)
{

SetSystemFields();

base.SubmitChanges(failureMode);
}

private void SetSystemFields()
{
ChangeSet changeset = this.GetChangeSet();

// retrieve the user name
System.Security.Principal.WindowsIdentity identity = System.Security.Principal.WindowsIdentity.GetCurrent();
string userName = &quot;Unknow&quot;;
if (identity != null)
{
userName = identity.Name;
}

// insert
int maxInserts = changeset.Inserts.Count;
for (int i = 0; i &lt; maxInserts; i++)
{
object entity = changeset.Inserts[i];
Type objectType = entity.GetType();
PropertyInfo[] properties = objectType.GetProperties();
foreach (PropertyInfo property in properties)
{
switch (property.Name.ToUpper())
{
case SystemFields.CreatedOn:
case SystemFields.ModifiedOn:
{
property.SetValue(entity, DateTime.Now, null);
} break;
case SystemFields.CreatedBy:
case SystemFields.ModifiedBy:
{
property.SetValue(entity, userName, null);
} break;
case SystemFields.IsDeleted:
{
property.SetValue(entity, false, null);
} break;
default:
break;
}
}
}

// update
int maxUpdates = changeset.Updates.Count;
for (int i = 0; i &lt; maxUpdates; i++)
{
object entity = changeset.Updates[i];
Type objectType = entity.GetType();
PropertyInfo[] properties = objectType.GetProperties();
foreach (PropertyInfo property in properties)
{
switch (property.Name.ToUpper())
{
case SystemFields.ModifiedOn:
{
property.SetValue(entity, DateTime.Now, null);
} break;
case SystemFields.ModifiedBy:
{
property.SetValue(entity, userName, null);
} break;
default:
break;
}
}
}

// deletes (logical deletes)
int maxDeletes = changeset.Deletes.Count;
for (int i = 0; i &lt; maxDeletes; i++)
{
object entity = changeset.Deletes[i];
Type objectType = entity.GetType();
PropertyInfo[] properties = objectType.GetProperties();
foreach (PropertyInfo property in properties)
{
switch (property.Name.ToUpper())
{
case SystemFields.ModifiedOn:
{
property.SetValue(entity, DateTime.Now, null);
} break;
case SystemFields.ModifiedBy:
{
property.SetValue(entity, userName, null);
} break;
case SystemFields.IsDeleted:
{
property.SetValue(entity, true, null);
} break;
default:
break;
}
}
}
}
}
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.sambeauvois.be/blog/2010/09/bring-a-bit-of-the-subsonic-power-to-linq-to-sql-by-adding-automatic-audit-and-logical-delete-fields/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<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>
		<item>
		<title>Custom paging with Subsonic 3 and ObjectDataSource in ASP.NET</title>
		<link>http://www.sambeauvois.be/blog/2010/04/custom-paging-with-subsonic-3-and-objectdatasource-in-asp-net/</link>
		<comments>http://www.sambeauvois.be/blog/2010/04/custom-paging-with-subsonic-3-and-objectdatasource-in-asp-net/#comments</comments>
		<pubDate>Thu, 22 Apr 2010 07:34:08 +0000</pubDate>
		<dc:creator>Sam Beauvois</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[SubSonic]]></category>

		<guid isPermaLink="false">http://www.sambeauvois.be/blog/?p=292</guid>
		<description><![CDATA[Here is how I created a paged items list in ASP.NET 3.5 using Subsonic for data access, and ASP.NET Controls for the display. I use Subsonic 3.0.0.4 with ActiveRecord and ASP.NET 3.5 SP1 webforms. For this example, we are creating a blog post list and that the DAL is created (the data class we use [...]]]></description>
			<content:encoded><![CDATA[<p>Here is how I created a paged items list in ASP.NET 3.5 using Subsonic for data access, and ASP.NET Controls for the display.</p>
<p>I use Subsonic 3.0.0.4 with ActiveRecord and ASP.NET 3.5 SP1 webforms.</p>
<p>For this example, we are creating a blog post list and that the DAL is created (the data class we use is &#8220;DAL.BlogPost&#8221;).</p>
<p>The DAL.BlogPost object has three properties we need : CreatedOn, Subject and Body.</p>
<h4>First step : prepare your data manager class</h4>
<pre class="brush: csharp; title: ;">

namespace MyBlog.BLL
{
   public class PostManager
   {
     // ...
   }
}
</pre>
<p>(keep in mind the namespace and the class for the nexts steps)</p>
<p>In this class, two methods are required,</p>
<p>The first returns the total number of items</p>
<pre class="brush: csharp; title: ;">

public int GetPostCount()
{
  return DAL.BlogPost.All().Count(x =&gt; x.IsDeleted != true);
}
</pre>
<p>The second one returns the items contained in a defined range (start index and then nomber of elements), so this method needs to know where to start and how many items to get.</p>
<pre class="brush: csharp; title: ;">

public PagedList&lt;DAL.BlogPost&gt; GetLastestPosts(int startRowIndex, int maximumRows)
{
   if (startRowIndex != 0)
   {
     startRowIndex =(startRowIndex/maximumRows);
   }

    IOrderedQueryable&lt;DAL.BlogPost&gt; yourQuery = DAL.BlogPost.All().OrderByDescending(x =&gt; x.CreatedOn);
    return new PagedList&lt;DAL.BlogPost&gt;(yourQuery, startRowIndex, maximumRows);
}
</pre>
<p>One important part to remember when using Subsonic is</p>
<pre class="brush: csharp; title: ;">

if (startRowIndex != 0)
{
   startRowIndex = startRowIndex / maximumRows;
}
</pre>
<p>This conversion is necessary because subsonic and the ObjectDataSource doesn&#8217;t share the same opinion about the paging method.<br />
Subsonic says</p>
<blockquote><p>&#8220;I want the third page containing five elements&#8221;</p></blockquote>
<p>ObjectDataSource says</p>
<blockquote><p>&#8220;I want the five elements following the third element&#8221;</p></blockquote>
<p>So the conversion is mandatory if you want a correct paging.</p>
<h4>Second step : create the aspx page.</h4>
<p>Declare an ObjectDataSource:</p>
<pre class="brush: xml; title: ;">
&lt;asp:ObjectDataSource runat=&quot;server&quot; ID=&quot;postsDataSource&quot;
 TypeName=&quot;Example.BLL.PostManager&quot;
 SelectMethod=&quot;GetLastestPosts&quot;
 EnablePaging=&quot;true&quot;
 SelectCountMethod=&quot;GetPostCount&quot; &gt;
 &lt;/asp:ObjectDataSource&gt;
</pre>
<p>Note the TypeName attribute : the value is the namespace + the class name of our datamanager class.<br />
We set the EnablePaging attribute to true and we specify the SelectCountMethod and the SelectMethod.</p>
<p>We don&#8217;t need any parameters for the paging, by default the MaximumRowsParameterName and StartRowIndexParameterName are set to &#8220;maximumRows&#8221; and &#8220;startRowIndex&#8221;.<br />
If we want other parameters names in our datamanager class, we can define them in the ObjectDataSource with these two parameters.</p>
<p>Add an asp ListView element</p>
<pre class="brush: xml; title: ;">
&lt;asp:ListView runat=&quot;server&quot; ID=&quot;postsListview&quot;
     DataSourceID=&quot;postsDataSource&quot;&gt;
 &lt;LayoutTemplate&gt;
    &lt;asp:PlaceHolder ID=&quot;itemPlaceHolder&quot;
         runat=&quot;server&quot; /&gt;
 &lt;/LayoutTemplate&gt;
 &lt;ItemTemplate&gt;
    &lt;h2&gt;&lt;%# Eval(&quot;CreatedOn&quot;,&quot;{0:d}&quot;)%&gt; :
     &lt;%# Eval(&quot;Subject&quot;) %&gt;&lt;/h2&gt;
    &lt;br /&gt;
    &lt;p&gt;
     &lt;%# Eval(&quot;Body&quot;) %&gt;
    &lt;/p&gt;
    &lt;hr /&gt;
 &lt;/ItemTemplate&gt;
&lt;/asp:ListView&gt;
</pre>
<p>Set the DataSourceID attribute to the ObjectDataSource ID parameter.</p>
<p>Define a LayoutTemplate and an ItemTemplate with the elements we want to display.</p>
<p>Then add an asp datapager control in the LayoutTemplate</p>
<pre class="brush: xml; title: ;">

&lt;LayoutTemplate&gt;

  &lt;asp:DataPager ID=&quot;postsDataPager&quot; runat=&quot;server&quot;
       PageSize=&quot;3&quot;&gt;
    &lt;Fields&gt;
      &lt;asp:NextPreviousPagerField ButtonType=&quot;Link&quot;
           FirstPageText=&quot;&lt;&lt;&quot; PreviousPageText=&quot;&lt;&quot;
           ShowNextPageButton=&quot;false&quot;
           ShowFirstPageButton=&quot;true&quot; /&gt;
      &lt;asp:NumericPagerField PreviousPageText=&quot;...&quot;
           NextPageText=&quot;...&quot; ButtonCount=&quot;10&quot; /&gt;
      &lt;asp:NextPreviousPagerField ButtonType=&quot;Link&quot;
           LastPageText=&quot;&gt;&gt;&quot; NextPageText=&quot;&gt;&quot;
           ShowPreviousPageButton=&quot;false&quot;
           ShowLastPageButton=&quot;true&quot; /&gt;
     &lt;/Fields&gt;
   &lt;/asp:DataPager&gt;

   &lt;asp:PlaceHolder ID=&quot;itemPlaceHolder&quot; runat=&quot;server&quot; /&gt;
 &lt;/LayoutTemplate&gt;
</pre>
<p>Here is the result :<br />
<a href="http://www.sambeauvois.be/blog/wp-content/uploads/2010/04/blogposts.png" target="_blank"><img class="aligncenter size-medium wp-image-307" title="blogposts" src="http://www.sambeauvois.be/blog/wp-content/uploads/2010/04/blogposts-300x178.png" alt="blogposts" width="300" height="178" /></a></p>
<h4>Remark about the data access method</h4>
<p>It&#8217;s possible to avoid the start index value conversion !</p>
<p>Check the PagedList first constructor code (<a href="http://github.com/subsonic/SubSonic-3.0/blob/master/SubSonic.Core/Schema/PagedList.cs" target="_blank">code is available on the subsonic git repository</a>)</p>
<pre class="brush: csharp; title: ;">

public PagedList(IQueryable&lt;T&gt; source, int index, int pageSize)
{
   int total = source.Count();
   TotalCount = total;
   TotalPages = total / pageSize;

   if(total % pageSize &gt; 0)
     TotalPages++;

   PageSize = pageSize;
   PageIndex = index;
   AddRange(source.Skip(index * pageSize).Take(pageSize).ToList());
}
</pre>
<p>As you can see, Subsonic use the Skip and the Take methods from Linq</p>
<p>So, you can modify the GetLastestPosts method to return a<span id="main" style="visibility: visible;"><span id="search" style="visibility: visible;"> strongly <em> </em></span></span> typed List in place of the PagedList:</p>
<pre class="brush: csharp; title: ;">

public List&lt;DAL.BlogPost&gt; GetLastestPosts(int startRowIndex, int maximumRows)
{
   return DAL.BlogPost.All().
          Skip(startRowIndex).
          Take(maximumRows).
          OrderByDescending(x =&gt; x.CreatedOn).
          ToList&lt;DAL.BlogPost&gt;();
}
</pre>
<p>With this method, no more conversion needed</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sambeauvois.be/blog/2010/04/custom-paging-with-subsonic-3-and-objectdatasource-in-asp-net/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

