Codesmith Templates for nHibernate and ASP.NET MVC

Filed in ActiveRecord | Codesmith 1 Comment

Reason #52356 I love using Castle’s ActiveRecord is that CRUD is automatically handled for you, which is a major time saver. I’m always looking for any edge to speed up the development process or automate redundant tasks, and that little drive led me to Codesmith Tools. What’s so cool about Codesmith? The fact that once you define a table — and all major databases are supported — clicking a single button can generate your class file, controller methods, stored procedures, or views.

I started using Codesmith with ASP.NET web forms, and when I first migrated to ASP.NET MVC, was unclear how/where to incorporate Codesmith into this new MVC environment. Well it was easier than I thought! Below I’m going to break down the Codesmith template file (.cst) I use to generate my ActiveRecord classes, which is done in c#:

Codesmith template references

The following section appears at the top of the template:

<%@ CodeTemplate Language="C#" TargetLanguage="C#" Description="Generates a very simple business object." %>
<%@ Property Name="SourceTable" Type="SchemaExplorer.TableSchema" Category="Context" Description="Table that the object is based on." %>
<%@ Property Name="Namespace" Type="System.String" Default="" Optional="False" Category="MethodInfo" %>
<%@ Assembly Name="SchemaExplorer" %>
<%@ Assembly Name="System.Data" %>
<%@ Import Namespace="SchemaExplorer" %>
<%@ Import Namespace="System.Data" %>

The most important rows to notice are the second and third. The SourceTable property tells Codesmith that you are going to choose a table which the rest of the code will reference. The Namespace property, which is tagged as optional, is simply a property I made up. In the code below, you will see how it is used. It is just a placeholder for the template, and you can have as many as you want.

Codesmith template

The next section is the template itself. It will look just like Classic ASP or MVC. In a nutshell, it is a block of text, with Codesmith markup appearing in between <% %> tags.

First we add the using namespaces our c# repository file will need to reference:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using NHibernate;
using NHibernate.Criterion;
using Castle.ActiveRecord;

Since this is an ActiveRecord class, and we use ICriterion for our queries, we include the NHibernate and ActiveRecord references. Next up is our namespace wrapper. You’ll notice the markup that references the Namespace property at the top of the page:

namespace <%= Namespace %>
{

Whatever you type into the textbox will pop in between the tags. Next up is the real meat: the class definition. You’ll notice all the ActiveRecord attributes above each property, as well as some methods, and finally the closing } for the namespace:

[ActiveRecord("<%= GetClassName(SourceTable) %>")]
public class <%= GetClassName(SourceTable) %> : ActiveRecordBase<<%= GetClassName(SourceTable) %>>
{
public <%= GetClassName(SourceTable) %>()
{
}

#region Properties
<% for (int i = 0; i < SourceTable.PrimaryKey.MemberColumns.Count; i++) { %>

[PrimaryKey(PrimaryKeyType.Native, "<%= SourceTable.PrimaryKey.MemberColumns[i].Name %>")]
public <%= GetCSharpVariableType(SourceTable.PrimaryKey.MemberColumns[i]) %> <%= SourceTable.PrimaryKey.MemberColumns[i].Name %> { get; set; }

<% } %>
<% for (int i = 0; i < SourceTable.NonPrimaryKeyColumns.Count; i++) { %>
[Property]
public <%= GetCSharpVariableType(SourceTable.NonPrimaryKeyColumns[i]) %> <%= GetPropertyName(SourceTable.NonPrimaryKeyColumns[i]) %> { get; set; }

<% if (i < SourceTable.NonPrimaryKeyColumns.Count - 1) Response.Write("\r\n"); %>
<% } %>
#endregion

#region Methods
public static void DeleteAll()
{
DeleteAll( typeof(<%= GetClassName(SourceTable) %>) );
}

public static <%= GetClassName(SourceTable) %>[] Find(ICriterion[] query, Order[] order)
{
return <%= GetClassName(SourceTable) %>.FindAll(order, query);
}
#endregion
}
}

The final section is a series of functions used by the template which extracts class names, database column types from the table, etc.:

<script runat="template">

public string GetPropertyName(ColumnSchema column)
{
string propertyName = column.Name;

if (propertyName == column.Table.Name + "Name") return "Name";
if (propertyName == column.Table.Name + "Description") return "Description";

if (propertyName.EndsWith("TypeCode")) propertyName = propertyName.Substring(0, propertyName.Length - 4);

return propertyName;
}

public string GetCSharpVariableType(ColumnSchema column)
{
if (column.Name.EndsWith("TypeCode")) return column.Name;

switch (column.DataType)
{
case DbType.AnsiString: return "string";
case DbType.AnsiStringFixedLength: return "string";
case DbType.Binary: return "byte[]";
case DbType.Boolean: return "bool";
case DbType.Byte: return "byte";
case DbType.Currency: return "decimal";
case DbType.Date: return "DateTime";
case DbType.DateTime: return "DateTime";
case DbType.Decimal: return "decimal";
case DbType.Double: return "double";
case DbType.Guid: return "Guid";
case DbType.Int16: return "short";
case DbType.Int32: return "int";
case DbType.Int64: return "long";
case DbType.Object: return "object";
case DbType.SByte: return "sbyte";
case DbType.Single: return "float";
case DbType.String: return "string";
case DbType.StringFixedLength: return "string";
case DbType.Time: return "TimeSpan";
case DbType.UInt16: return "ushort";
case DbType.UInt32: return "int";
case DbType.UInt64: return "ulong";
case DbType.VarNumeric: return "decimal";
default:
{
return "__UNKNOWN__" + column.NativeType;
}
}
}

public string GetClassName(TableSchema table)
{
if (table.Name.EndsWith("s"))
{
return table.Name.Substring(0, table.Name.Length - 1);
}
else
{
return table.Name;
}
}
</script>

When executed, the above code creates your class file, ready for copying and pasting into your project, and fully crud-enabled. A brilliant little feature Codesmith includes is a running counter of how many lines of code it has generated for you, along with the ability to set your hourly rate and however many lines of code you can manually generate per hour, so you can see your ROI.

, , , , ,

How to implement paging with c#, mvc, nHibernate, ICriterion

Filed in ASP.NET MVC | C# | NHibernate Leave a comment

There is a really cool jQuery tool (http://tablesorter.com/docs/index.html) that uses PFM Technology (Pure Freakin’ Magic) to make your html table just magically page and sort. It works great with MVC and nHibernate, but I wanted to get fancy and make my own. Turned out to be surprisingly easy. Here’s what I did:

Preparing the Controller

1. Create you search criteria:

ICriterion[] query = { Expression.Eq(FieldName, FieldValue) };

2. Get the total record count matching the criteria without actually pulling back all the records. I throw the count into a ViewData variable for later processing on the page:

int count = ActiveRecordMediator<listing>.Count(query);
ViewData["count"] = count;

3. Execute a SlicedFindAll search to only get the subset instead of the entire recordset.

Contact[] pagedContacts = Contact.SlicedFindAll((currentPageIndex) * Rows), Rows, query);

The currentPageIndex variable is passed in from the page. At this point, the controller is ready!

Preparing the View

1. First we will create links to the individual pages. This is also where we use the ViewData["count"] value:

int TotalListings = int.Parse(ViewData["count"].ToString());
int RecordsPerPage = 15;    // <-- this can be defined anywhere, I wired it for this demo
int TotalPages = (TotalListings + RecordsPerPage - 1) / RecordsPerPage;

StringBuilder sb = new StringBuilder();
if (TotalPages > 1)
{
for (int i = 0; i < TotalPages; i++)
{
sb.Append("<a href='/your-url-path/" + i.ToString() + "'>" + (i + 1).ToString() + "</a>&nbsp;&nbsp;");
}

Response.Write(sb.ToString());
}

2. Loop through your recordset, adding your rows.

3. Add an optional footer:

if (TotalPages > 1)
{
Response.Write(sb.ToString());
}

That’s it! This could easily be extended to include next, previous, etc. links, but for demo purposes this works well.

, ,

How To Create a Class with ActiveRecord

Filed in ActiveRecord | C# | NHibernate Leave a comment

So in this installment, we’re going to look at what goes into creating a class using ActiveRecord. One of the cool parts of ActiveRecord is the fact that you don’t have to waste time with CRUD statements because they are baked in for you! So here is the anatomy of a class:

1. The using statements:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using NHibernate;
using NHibernate.Criterion;
using Castle.ActiveRecord;

I created some CodeSmith templates which I use to generate all my classes, the above using statements are my defaults. Next is the class name, the required attributes, and the properties:

[ActiveRecord("<em>TABLE NAME</em>")]
public class Contact : ActiveRecordBase&lt;Contact&gt;
{
public Contact()
{
}

[PrimaryKey(PrimaryKeyType.Native, "ID")]
public int ID { get; set; }

[Property]
public string FirstName { get; set; }

[Property]
public string LastName { get; set; }

[Property]
public string State { get; set; }

[Property]
public DateTime CreationDate { get; set; }

[Property(Column="CreatedByUser"]
public int OwnerUserID { get; set; }

The [Property] attribute indicates that field exists in the table. If you don’t include [Property] then that field will not be included in CRUD statements. Also, if you want the property name to be different from the database column name, simply set Column=ColumnName like the “CreatedByUser” sample above.

, ,

TOP