Introduction
To learn more about Smart Code please read the next article, by clicking
here.
The sample code and templates, are based in the next article NHibernate Best Practices with ASP.NET . In this excellent
article, Billy McCafferty, describes best practices for leveraging the benefits
of NHibernate 1.2, ASP.NET.
For this article we'll try to be original.....and we'll use the Northwind database as sample, but these examples will
work with any databases
Bug Fix on ASPX templates, loading page by ID method
Code Generation, a brief overview
The Smart Code tool makes possible the automatic generation of programs and components
that interact with database systems. It works by reading a database schema, allowing
the user to set certain extended properties for tables and columns, and applying
templates to each table in order to generate code. The templates are themselves
programs that access the Smart Code Object Model to produce tailored programs and
components. Although Smart Code comes with a set of basic templates, users may edit
these or create their own to suit their particular project needs. Moreover, templates
may be written in C# or VB.NET (or theoretically in any .NET language that supports
the creation of dynamic-link libraries).
Quick Start Guide
Smart Code is a very powerful tool, and perhaps the best way to learn how to use
it is to see a sample application running and then go back and examine which features
of Smart Code were responsible for the application's functionality.
- On the web.config and modify the connection.connection_string value
- Play with the application, open up different pages and entering some data.
- Open the Newin.scp project with the last release of Smart Code.
- Compile the NHibernateTemplates and WebTemplates and Load the dlls into Smart Code.
- Change some properties in Newin.scp project, this will show you the effect of different
attribute settings and template assignments.
The NHibernate Template Libraries
The Sample package comes with one set of template libraries for generating 3- tier,
web-form-based solutions that use NHibernate to access and modify data. This set
of libraries is for generating code in C#; (future releases will support generating
code in VB.NET).
In addition, the Sample package includes sample Northwind project in Visual Studio.NET
to work with these sets of libraries, so that the generated code may simply be dragged-and-dropped
into them.
The Domain Layer
For a description about the domain layer, click here
The Domain layer describing the data access objects and the classes of objects used
to transport data between the tiers
Generating the Separated Interface, IDAOFactory
The IDAOFactory Interface provide methods to get objects as DAOs. This class serves
as the abstract data. The template to generate the IDAOFactory for all entities
in the Smart Code project is the IDaoFactory class in the NHibernateTemplates project.
Notice, if you check the Item it Template run only one time, because it is an project
level template.
The Code Generated for the IDAOFactory look like this:
using System;
using System.Collections.Generic;
namespace Northwind.Core.DataInterfaces
{
public interface IDaoFactory
{
ICategoryDao GetCategoryDao();
ICustomerCustomerDemoDao GetCustomerCustomerDemoDao();
ICustomerDemographicDao GetCustomerDemographicDao();
ICustomerDao GetCustomerDao();
IEmployeeDao GetEmployeeDao();
IEmployeeTerritoryDao GetEmployeeTerritoryDao();
IOrderDetailDao GetOrderDetailDao();
IOrderDao GetOrderDao();
IProductDao GetProductDao();
IRegionDao GetRegionDao();
IShipperDao GetShipperDao();
ISupplierDao GetSupplierDao();
ITerritoryDao GetTerritoryDao();
}
}
The Data Interfaces
The template DataInterfaces generate code for supporting each one concrete
DAO factory. Each factory is an is a database-independent implementation, where
the implementations will be database specific.
The Template used to generate the DataInterfaces is shwon in the next figure:
And the code generated, for the Product Table look like this
using System;
using System.Collections.Generic;
using Northwind.Core.Domain;
namespace Northwind.Core.DataInterfaces
{
public interface IProductDao : IDao<Product, System.Int32>
{
}
}
Mapping the Domain to the Database, HBM-XML files
The NHibernateTemplates project provide a class NHibernateHbm, to generate mapping
files for NHibernate
This Template generate the HBM files, for tables with single and composite Key and
linking tables which will be recognised and the appropriate many-to-one or many-to-many
mapping created
Hbm for Table with single key:
="1.0" ="utf-8"
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Northwind.Core" namespace="Northwind.Core.Domain">
<class name="Product" table="Products" >
<id name="ID" type="System.Int32" column="ProductID">
<generator class="identity"/>
</id>
<property name="ProductName" column="ProductName" type="System.String" not-null="true" length="40"/>
.............
<many-to-one name="CategoryIDCategories" column="CategoryID" class="Category" update="0" insert="0" />
<many-to-one name="SupplierIDSuppliers" column="SupplierID" class="Supplier" update="0" insert="0" />
<bag name="OrderDetailses" table="Order Details" inverse="true" lazy="true" cascade="delete">
<key column="ProductID" />
<one-to-many class="OrderDetail"/>
</bag>
</class>
</hibernate-mapping>
Hbm for Table with composite key:
="1.0" ="utf-8"
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Northwind.Core" namespace="Northwind.Core.Domain">
<class name="EmployeeTerritory" table="EmployeeTerritories" >
<composite-id name="ID" class="Northwind.Core.Domain.EmployeeTerritory+DomainObjectID">
<key-property type="System.Int32" name="EmployeeID" column="EmployeeID" />
<key-property type="System.String" name="TerritoryID" column="TerritoryID" />
</composite-id>
<many-to-one name="EmployeeIDEmployees" column="EmployeeID" class="Employee" update="0" insert="0" />
<many-to-one name="TerritoryIDTerritories" column="TerritoryID" class="Territory" update="0" insert="0" />
</class>
</hibernate-mapping>
The many-to-one and bag are created from the Foreing Key relationship between the
tables (InReferences and OutReferences) these references are created when you build
the Domain, the next figure shown this concept:
Both tables Products and Territories are related by Out References (OutReferences),
with the EmployeeTerritories (InReferences).
Generating the C# class
The NHibernateTemplates project provide the class NHibernateClass, to generate the
C# class for NHibernate
As the mapping, the NHibernateClass support single and composite key, about the
IDs please refeer to Generic IDs and Object Comparisons section in the NHibernate
Best Practices with ASP.NET Article.
The next code shows a sample how the code for composite keys are generated:
using System;
using System.Collections.Generic;
namespace Northwind.Core.Domain
{
[Serializable]
public class EmployeeTerritory : DomainObject<EmployeeTerritory.DomainObjectID>
{
[Serializable]
public class DomainObjectID
{
private System.Int32 _EmployeeID;
private System.String _TerritoryID;
public DomainObjectID() { }
public DomainObjectID(System.Int32 employeeID, System.String territoryID)
{
_EmployeeID = employeeID;
_TerritoryID = territoryID;
}
public System.Int32 EmployeeID
{
get { return _EmployeeID; }
protected set { _EmployeeID = value; }
}
public System.String TerritoryID
{
get { return _TerritoryID; }
protected set { _TerritoryID = value; }
}
public override bool Equals(object obj)
{
if (obj == this) return true;
if (obj == null) return false;
DomainObjectID that = obj as DomainObjectID;
if (that == null)
{
return false;
}
else
{
if (this.EmployeeID != that.EmployeeID) return false;
if (this.TerritoryID != that.TerritoryID) return false;
return true;
}
}
public override int GetHashCode()
{
return EmployeeID.GetHashCode() ^ TerritoryID.GetHashCode();
}
}
private Employee _EmployeeIDEmployees;
private Territory _TerritoryIDTerritories;
public EmployeeTerritory()
{
}
public EmployeeTerritory(DomainObjectID id)
{
base.id = id;
}
public virtual System.Int32 EmployeeID
{
get { return base.id.EmployeeID; }
}
public virtual System.String TerritoryID
{
get { return base.id.TerritoryID; }
}
public virtual Employee EmployeeIDEmployees
{
get { return _EmployeeIDEmployees; }
set { _EmployeeIDEmployees = value; }
}
public virtual Territory TerritoryIDTerritories
{
get { return _TerritoryIDTerritories; }
set { _TerritoryIDTerritories = value; }
}
public override int GetHashCode()
{
return ID.GetHashCode();
}
}
}
Where EmployeeTerritory+DomainObjectID overrides the Equals and GetHashCode Methods.
Web Forms for Listing Records
These templates generate Web Forms for listing records. All of them display records
in an ASPGrid, 20 records at a time (by default), with controls for browsing the
grid's contents; also, column headers may be clicked to sort rows and paging.
Each row in the grid has hyperlinks to edit and view the corresponding record, and
the pages include a "Add" button to create a new record. The grid is automatically
populate when the page is loaded
Web Forms for Editing Records
These templates generate Web Forms for creating and editing records.
Moreover, these templates recognize attributes like the Control property has been
set to ComboBox or Check Box.
The ComboBox control combinated with LOV property, produce custom DataTextField
properties in the dropDown Web Control.
Summary
The possibilities for Smart Code templates are unlimited. Smart Code is an exceptionally
powerful developer productivity tool. Coupled with the NHibernate templates you
can write the base code for your application in a matter of minutes.
Web Application Project
The Sample Code uses the Web Application Project type of website for building web
applications. This kind of web site is very similar to the .Net Framework 1.1 model.
You can get the installer for Web Application Projects at
http://download.microsoft.com/download/9/0/6/906064ce-0bd1-4328-af40-49dca1aef87c/WebApplicationProjectSetup.msi.
After downloading it you can just run it.
Changelog
- Minor bug fix in composite-key definition