Adding NHibernate support to Steve Sanderson’s SportsStore
May 2nd
Of all the ASP.NET MVC books out there Steve Sanderson’s Pro ASP.NET MVC Framework is, in my opinion, probably one of the best. The author’s writing style and explanations are excellent. He covers MVC 1.0 in great detail and although I generally hate exclusive case study books this book devotes 3 of it’s 15 chapters to looking at developing a small shopping cart application. Steve introduces quite a few good pratices such as recognised design patterns eg Repository Pattern, Inversion of Control (IOC)/Dependency Injection (DI) and the use of mocking tools (namely Moq). He approaches the development from both a Domain Driven Design (DDD) and Test Driven Development (TDD) perspective although, as he stresses, you are not obliged to follow the testing style if it doesn’t suit you.
Anyway getting to the point of this post: SportsStore uses IOC to loosely couple the components of the application, this allows for easier testing and the ability to swap out dependencies. SportsStore uses the popular Castle Windsor container to facilitate IOC. In doing so the application is able to easily use any data persistence technology it chooses. Steve chose to use LinqToSql as the data persistence choice but I’m not that keen on it as it introduces a slight ‘dusting’ on the application’s domain model entities (and ties it to SQL Server). I like my business objects to be clean and free from any attributes. One of NHibernate’s nice features is it’s persistence ignorance. It leaves your domain entities clean, they dont have to implement any special interface or have any attributes applied to them.
So with all that said let’s quickly add NHibernate support to SportStore:
- Download the latest NHibernate binaries here
- In SportsStore’s DomianModel project create a new root folder called NHibernateBinaries and put the NHibernate.dll in there.
- Add a reference to the NHibernate.dll
- In the Entities folder create a NHibernate mapping file for the products entity:
It should look like this:<?xml version="1.0" encoding="utf-8" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"> <class name="DomainModel.Entities.Product, DomainModel" table="Products"> <id name="ProductID" type="Int32" unsaved-value="null"> <column name="ProductID" length="16" sql-type="int" not-null="true" unique="true" index="PK_Product"/> <generator /> </id> <property name="Name" type="String"> <column name="Name" length="100" sql-type="nvarchar" not-null="true"/> </property> <property name="Description" type="String"> <column name="Description" length="500" sql-type="nvarchar" not-null="true"/> </property> <property name="Price" type="Decimal"> <column name="Price" length="16" sql-type="decimal" not-null="false"/> </property> <property name="Category" type="String"> <column name="Category" length="50" sql-type="nvarchar" not-null="true"/> </property> </class> </hibernate-mapping>
name this file Product.hbm.xml
- In the Concrete folder of SportsStore Add this class NHibernateSessionManager.cs
using System; using System.Collections.Generic; using System.Configuration; using System.Runtime.Remoting.Messaging; using System.Text; using NHibernate; using NHibernate.Cache; using System.Web; using System.Data; namespace DomainModel.Concrete { /// <summary> /// Handles creation and management of sessions and transactions. It is a singleton because /// building the initial session factory is very expensive. Inspiration for this class came /// from Chapter 8 of Hibernate in Action by Bauer and King. Although it is a sealed singleton /// you can use TypeMock (http://www.typemock.com) for more flexible testing. /// </summary> public sealed class NHibernateSessionManager { #region Thread-safe, lazy Singleton /// <summary> /// This is a thread-safe, lazy singleton. See http://www.yoda.arachsys.com/csharp/singleton.html /// for more details about its implementation. /// </summary> public static NHibernateSessionManager Instance { get { return Nested.nHibernateSessionManager; } } /// <summary> /// Initializes the NHibernate session factory upon instantiation. /// </summary> private NHibernateSessionManager() { InitSessionFactory(); } /// <summary> /// Assists with ensuring thread-safe, lazy singleton /// </summary> private class Nested { static Nested() { } internal static readonly NHibernateSessionManager nHibernateSessionManager = new NHibernateSessionManager(); } #endregion private void InitSessionFactory() { NHibernate.Cfg.Configuration cfg = new NHibernate.Cfg.Configuration(); // The following makes sure the the web.config contains a declaration for the HBM_ASSEMBLY appSetting if (ConfigurationManager.AppSettings["HBM_ASSEMBLY"] == null || ConfigurationManager.AppSettings["HBM_ASSEMBLY"] == "") { throw new ConfigurationErrorsException("NHibernateManager.InitSessionFactory: \"HBM_ASSEMBLY\" must be " + "provided as an appSetting within your config file. \"HBM_ASSEMBLY\" informs NHibernate which assembly " + "contains the HBM files. It is assumed that the HBM files are embedded resources. An example config " + "declaration is <add key=\"HBM_ASSEMBLY\" value=\"MyProject.Core\" />"); } cfg.AddAssembly(System.Configuration.ConfigurationManager.AppSettings["HBM_ASSEMBLY"]); sessionFactory = cfg.BuildSessionFactory(); } /// <summary> /// Allows you to register an interceptor on a new session. This may not be called if there is already /// an open session attached to the HttpContext. If you have an interceptor to be used, modify /// the HttpModule to call this before calling BeginTransaction(). /// </summary> public void RegisterInterceptor(IInterceptor interceptor) { ISession session = threadSession; if (session != null && session.IsOpen) { throw new CacheException("You cannot register an interceptor once a session has already been opened"); } GetSession(interceptor); } public ISession GetSession() { return GetSession(null); } /// <summary> /// Gets a session with or without an interceptor. This method is not called directly; instead, /// it gets invoked from other public methods. /// </summary> private ISession GetSession(IInterceptor interceptor) { ISession session = threadSession; if (session == null) { if (interceptor != null) { session = sessionFactory.OpenSession(interceptor); } else { session = sessionFactory.OpenSession(); } threadSession = session; } return session; } public void CloseSession() { ISession session = threadSession; threadSession = null; if (session != null && session.IsOpen) { session.Close(); } } public void BeginTransaction(IsolationLevel il) { ITransaction transaction = threadTransaction; if (transaction == null) { transaction = GetSession().BeginTransaction(il); threadTransaction = transaction; } } public void CommitTransaction() { ITransaction transaction = threadTransaction; try { if (transaction != null && !transaction.WasCommitted && !transaction.WasRolledBack) { transaction.Commit(); threadTransaction = null; } } catch (HibernateException ex) { RollbackTransaction(); throw ex; } } public void RollbackTransaction() { ITransaction transaction = threadTransaction; try { threadTransaction = null; if (transaction != null && !transaction.WasCommitted && !transaction.WasRolledBack) { transaction.Rollback(); } } catch (HibernateException ex) { throw ex; } finally { CloseSession(); } } private ITransaction threadTransaction { get { return (ITransaction)CallContext.GetData("THREAD_TRANSACTION"); } set { CallContext.SetData("THREAD_TRANSACTION", value); } } private ISession threadSession { get { return (ISession)CallContext.GetData("THREAD_SESSION"); } set { CallContext.SetData("THREAD_SESSION", value); } } private ISessionFactory sessionFactory; } }also add a new NHibernateProductsRespository.cs class
using System; using System.Collections.Generic; using System.Linq; using System.Data.Linq; using System.Text; using DomainModel.Abstract; using DomainModel.Entities; using NHibernate; using NHibernate.Expression; namespace DomainModel.Concrete { public class NHibernateProductsRepository : IProductsRepository { private static IList<Product> GetProducts() { ISession isess = NHibernateSessionManager.Instance.GetSession(); return isess.CreateCriteria(typeof(Product)) .AddOrder(Order.Asc("Name")) .List<Product>(); } public IQueryable<Product> Products { get { return GetProducts().AsQueryable(); } } } } - Finally modify your web.config to add the NHibernate sections
<configSections> <section name="castle" type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" /> <section name="nhibernate" type="System.Configuration.NameValueSectionHandler, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/> </configSections> <nhibernate> <add key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider"/> <add key="hibernate.dialect" value="NHibernate.Dialect.MsSql2000Dialect"/> <add key="hibernate.connection.driver_class" value="NHibernate.Driver.SqlClientDriver"/> <add key="hibernate.connection.connection_string" value="Data Source = yourserver;Initial Catalog = SportsStore;user id=sa;password=yourpassword;"/> </nhibernate> <appSettings> <add key="HBM_ASSEMBLY" value="DomainModel"/> </appSettings>
Compile the solution and now you are free to change your implementation of Products repository to the NHibernateProductsRespository by altering the castle component in your web.config:

Terser and terser code
Apr 28th
Not too long ago we all wrote code like this. For example consider the following where we pass a method name as a parameter to a method that accepts a delegate.
delegate int numberFunction (int integer);
public class UsingFunc2 {
static int GetMe(int int1, numberFunction numberFunction) {
int int2 = 7;
return numberFunction(int2) + int1;
}
public static int MyNumberFunction(int x){
return x*x;
}
static void Main() {
Console.WriteLine(GetMe(5, MyNumberFunction));
}
Then along came anonymous functions which enabled us to dispose of explicitly defining the function to be passed as a parameter in favour of the in-situ delegate syntax.
delegate int numberFunction (int integer);
public class UsingFunc2 {
static int GetMe(int int1, numberFunction numberFunction) {
int int2 = 7;
return numberFunction(int2) + int1;
}
static void Main() {
Console.WriteLine(GetMe(5, delegate(int x) { return x * x; }));
}
}
Soon we were able to dispense with actually declaring the delegate at all by making use of Func. The Func type provides a way to store anonymous methods in a generalized and simple way.
static int GetMe(int int1, Func<int, int> numberFunction) {
int int2 = 7;
return numberFunction(int2) + int1;
}
static void Main() {
Console.WriteLine(GetMe(5, delegate(int x) { return x * x; }));
}
Finally with Lambda methods we have a much terser way to write anonymous methods. Notice that the Lambda expression infers the type from the Func declaration:
static int GetMe(int int1, Func<int, int> numberFunction) {
int int2 = 7;
return numberFunction(int2) + int1;
}
static void Main() {
Console.WriteLine(GetMe(5, x => x * x));
}
6 months of MVC and no looking back
Feb 12th
Having had my gut full of corrupted viewstates, no control over html, strange things happening in server control events etc etc I decided to ditch web forms for good in favour of ASP.NET MVC and jQuery. That was 6 months ago and it’s like a breath of fresh air – I actually enjoy web development again! – I now get to write javascript – something I havent done since classic ASP days. It’s strange but it feels so natural and clean to develope in MVC. I’d nearly go as far as saying that you can’t help but write great loosely coupled architecture. I shudder when I see codebehind classes these days.
Syntax Highlighter is cool
Oct 2nd
I’m just testing out Syntax Highlighter and it’s the dogzblx for publishing code snippets eg:
using System;
using System.Collections;
using System.Data;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
namespace steve.BindingCustomCollections3.ObjectDeclarations{
[Serializable]
[XmlRoot("Employees")]
public class Employees: ICollection{
private DataTable employeeTable;
private DataView employeeView;
internal Employees(DataTable employeeTable){
this.employeeTable = employeeTable;
this.employeeView = new DataView(employeeTable, "", "", DataViewRowState.CurrentRows);
this.employeeView.ApplyDefaultSort = true;
}
public int Count{
get{
return (employeeView.Count);
}
}
public Employee this[int indexer]{
get {
//Check if the indexer falls in allowable range.
if ((indexer >= 0) &&
(indexer < employeeView.Count))
return (new Employee(employeeView[indexer].Row));
else
throw new System.IndexOutOfRangeException("Index must be between 0 and " +
employeeView.Count.ToString() + ".");
}
}
public Employee FindById(int id){
int index = employeeView.Find(id);
if(index == -1){
return null;
}
else{
return(new Employee(employeeView[index].Row));
}
}
public IEnumerator GetEnumerator(){
return new EmployeesEnumerator(employeeView);
}
public object SyncRoot{
get{return employeeTable.Rows.Count;}
}
public bool IsSynchronized{
get{return false;}
}
public void CopyTo(Array a, int offset){
for(int index = 0; index < this.Count; index++){
a.SetValue(new Employee(employeeView[index].Row), index + offset);
}
}
}
}
My never ending Ajax hassle
Aug 13th
OK so I have played about with Ajax years ago but I’ve always been skeptical about including it in enterprise applications due to the grief it gives me. Most of the Ajax I put in applications invariably causes me to rip it out at some point or other. I really like the effects of Ajax but it frustrates me that it breaks existing functionality.
This week for the first time in ages I thought ok lets give Ajax another chance.
This is the scenario: I have a masterpage which contains a header user control, in that header user control is a ‘login’ hyperlink that directs to a login page where a user can get authenticated etc. I thought it would be neat to use a ModalPopupExtender with a panel so that the login functionality would not require a full postback etc. So I include my login panel and ModalPopupExtender in my header control and plumb in the authentication code etc. All works fine. But then as I go into my admin section I find that pages (which derive from the same masterpage) that contain other user and custom controls dont function correctly. In particular I have a page which contains a control with a datagrid (yes datagrid – its an old app) inside it. The OnUpdateCommand now doesnt fire. Ive tried changing the way I hook up the event handlers eg:
this.dgEditor.UpdateCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.dgEditor_UpdateCommand);
or decleratively within the Datagrid markup. Neither makes a difference.
However if I comment the Ajax modal popup and associated panel then all works again. I get frustrated because I feel I should not have to spend time debugging this kind of stuff. I’d rather be debugging more important complex buisness logic.
Anyway rather than submit the code yet does anyone else have these kind of issues and am I missing something when I assume I can quickly just plumb in some stuff from the Ajax toolkit and expect it not to break existing, seemingly unrelated code.
Viewing legacy database diagrams in Management Studio
Aug 3rd
Ok so I’m not a DBA and dont really know why this works but it does. When developing my database applications in SQL Server 2000 I usually enforce referential integrity using the database diagram facility in Enterprise Manager. Obviously now I’m using Management Studio I still have to look at or import Server 2000 databases in Management Studio. One error that constantly crops up after I’ve restored an old 2000 db to a new 2005 db is that when I try to view the db diagram in MS I get the following error message:
“Database diagram support objects cannot be installed because this database does not have a valid owner. To continue, first use the Files page of the DB properties dialog box or the Alter Authorization statement to set the DB owner to a valid login, then add the database diagram support objects.”
I tried messing about with the owners etc but to no avail. The following however works:
Set the compatibility level through SQL Server Management Studio by right-clicking on the Northwind database and selecting Properties. From the Properties page, you can select the 90 compatibility level.
Once you’ve changed the level, try the database diagram tool again.

Hey presto! .. works everytime
3d graphics with Silverlight 2 and Xaml
Apr 18th
This week I’ve taken some time out to play with the new Silverlight 2 release from Microsoft. I can’t say I was that impressed with previous versions but this release ROCKS. I’ve looked at loads of examples in the last 2 days and here is something I’ve modified off the net in order to make an interactive spinning cube.
Update: I’ve now updated this so it works in Visual Studio 2010
First create xaml file – here is the code
<UserControl x:Class="SilverlightApplication1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="Black">
<Canvas x:Name="parentCanvas"
xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Loaded="Page_Loaded"
Width="640"
Height="480"
Background="Red"
>
<Canvas x:Name="spinningCubeCanvas">
<Canvas.Resources>
<Storyboard x:Name="spinningCubeStorybard" Completed="spinningCubeCanvas_Render"/>
</Canvas.Resources>
</Canvas>
<TextBlock x:Name="debugText" FontFamily="Arial" FontSize="11" Foreground="White"/>
</Canvas>
</Grid>
</UserControl>
Now add the C# to the ‘Code Behind’
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace SilverlightApplication1 {
public partial class MainPage : UserControl {
private static readonly double CubeXSize = 150;
private static readonly double CubeYSize = 150;
private static readonly double CubeZSize = 150;
private class Vertex {
public double X, Y, Z;
public double RotatedX, RotatedY, RotatedZ;
public int TranslatedX, TranslatedY;
}
private class Face {
public int VertexA, VertexB, VertexC;
}
private DateTime _prevTime;
private Vertex[] _vertices = new Vertex[] {
new Vertex() { X=-CubeXSize, Y=-CubeYSize, Z=-CubeZSize},
new Vertex() { X=CubeXSize, Y=-CubeYSize, Z=-CubeZSize},
new Vertex() { X=-CubeXSize, Y=CubeYSize, Z=-CubeZSize},
new Vertex() { X=CubeXSize, Y=CubeYSize, Z=-CubeZSize},
new Vertex() { X=-CubeXSize, Y=-CubeYSize, Z=CubeZSize},
new Vertex() { X=CubeXSize, Y=-CubeYSize, Z=CubeZSize},
new Vertex() { X=-CubeXSize, Y=CubeYSize, Z=CubeZSize},
new Vertex() { X=CubeXSize, Y=CubeYSize, Z=CubeZSize},
};
private Face[] _faces = new Face[] {
new Face() { VertexA=2, VertexB=1, VertexC=0},
new Face() { VertexA=1, VertexB=2, VertexC=3},
new Face() { VertexA=4, VertexB=5, VertexC=6},
new Face() { VertexA=7, VertexB=6, VertexC=5},
new Face() { VertexA=0, VertexB=4, VertexC=6},
new Face() { VertexA=0, VertexB=6, VertexC=2},
new Face() { VertexA=7, VertexB=5, VertexC=1},
new Face() { VertexA=3, VertexB=7, VertexC=1},
new Face() { VertexA=5, VertexB=4, VertexC=0},
new Face() { VertexA=1, VertexB=5, VertexC=0},
new Face() { VertexA=2, VertexB=6, VertexC=7},
new Face() { VertexA=2, VertexB=7, VertexC=3},
};
private double _xRotation = 0;
private double _yRotation = 0;
private double _zRotation = 0;
public MainPage() {
InitializeComponent();
}
public void Page_Loaded(object o, EventArgs e) {
// Required to initialize variables
InitializeComponent();
this._prevTime = DateTime.Now;
this.spinningCubeStorybard.Begin();
}
public void spinningCubeCanvas_Render(object sender, EventArgs e) {
double tempX1;
double tempY1;
double tempZ1;
double focalLength = 280;
double zoom = 500;
int xoffset = 320;
int yoffset = 240;
if (this.Parent is Canvas) {
xoffset = (int)(((Canvas)this.Parent).Width / 2);
yoffset = (int)(((Canvas)this.Parent).Height / 2);
}
// Calculate all the vertices
foreach (Vertex vertex in this._vertices) {
// Rotate the vertex around the Z axis
tempY1 = (vertex.X * Math.Sin(this._zRotation)) + (vertex.Y * Math.Cos(this._zRotation));
tempX1 = (vertex.X * Math.Cos(this._zRotation)) - (vertex.Y * Math.Sin(this._zRotation));
// Rotate the vertex around the Y axis
vertex.RotatedX = (vertex.Z * Math.Sin(this._yRotation)) + (tempX1 * Math.Cos(this._yRotation));
tempZ1 = (vertex.Z * Math.Cos(this._yRotation)) - (tempX1 * Math.Sin(this._yRotation));
// Rotate the vertex around the X axis
vertex.RotatedZ = (tempY1 * Math.Sin(this._xRotation)) + (tempZ1 * Math.Cos(this._xRotation));
vertex.RotatedY = (tempY1 * Math.Cos(this._xRotation)) - (tempZ1 * Math.Sin(this._xRotation));
// Translate the vertex into a 2D coordinate
vertex.TranslatedX = ((int)((vertex.RotatedX * focalLength) / (vertex.RotatedZ + zoom))) + xoffset;
vertex.TranslatedY = ((int)((vertex.RotatedY * focalLength) / (vertex.RotatedZ + zoom))) + yoffset;
}
// Create polygons for Silverlight to work with from the newly calculated vertices
this.spinningCubeCanvas.Children.Clear();
foreach (Face face in this._faces) {
Vertex vertexA = this._vertices[face.VertexA];
Vertex vertexB = this._vertices[face.VertexB];
Vertex vertexC = this._vertices[face.VertexC];
// Do a mixedproduct of all vertices for hidden surface removal
double mixedProduct = (vertexB.TranslatedX - vertexA.TranslatedX) * (vertexC.TranslatedY - vertexA.TranslatedY) -
(vertexC.TranslatedX - vertexA.TranslatedX) * (vertexB.TranslatedY - vertexA.TranslatedY);
bool visible = mixedProduct < 0;
if (!visible) {
continue;
}
// Use the mixed product for "shading". The larger the face, the brighter it is.
double shade = -mixedProduct; // *512;
shade /= 1024;
int color = (int)shade;
color += 128;
if (color >= 250) {
color = 250;
}
if (color < 30) {
color = 30;
}
byte red = (byte)(color >> 3);
byte green = (byte)(color >> 1);
byte blue = (byte)(color);
// Create the polygon and initialize the point and the color
Polygon polygon = new Polygon();
//polygon.Points = new Point[] {
// new Point(vertexA.TranslatedX,vertexA.TranslatedY),
// new Point(vertexB.TranslatedX,vertexB.TranslatedY),
// new Point(vertexC.TranslatedX,vertexC.TranslatedY)
// };
polygon.Points = new PointCollection();
polygon.Points.Add(new Point(vertexA.TranslatedX, vertexA.TranslatedY));
polygon.Points.Add(new Point(vertexB.TranslatedX, vertexB.TranslatedY));
polygon.Points.Add(new Point(vertexC.TranslatedX, vertexC.TranslatedY));
polygon.Fill = new SolidColorBrush(Color.FromArgb(red, green, blue, red));
this.spinningCubeCanvas.Children.Add(polygon);
}
// Change the angles of the cube
this._xRotation += 0.01;
this._yRotation += 0.02;
this._zRotation += 0.03;
// Calculate the FPS (Frames Per Second) and display it
DateTime now = DateTime.Now;
TimeSpan frameTime = now.Subtract(this._prevTime);
this._prevTime = now;
int fps = frameTime.Seconds < 1 ? 1000 / ((frameTime.Milliseconds == 0) ? 1 : frameTime.Milliseconds) : 0;
this.debugText.Text = "FPS : " + fps;
this.spinningCubeStorybard.Begin();
}
}
}
You can download the solution file here