Category: Using NConstruct Builder
Target NConstruct Versions: 2.x
Document Release Date: November, 2009
2. Solution
Separating generated and customized code
Data Transfer Object
Entity
Updating object model
3. Practical Examples
Case 1: A new field in existing table
Updated classes and files
ShippersDTO.Generated.cs class
ShippersEntity.Generated.cs class
ShippersEntity.hbm.xml file
ShippersEntity.cs
class
Case 2: A new table with a relation to an existing table
New classes and files
Updated classes and files
ShippersDTO.Generated.cs class
ShippersEntity.Generated.cs class
ShippersEntity.hbm.xml file
ShippersEntity.cs
class
There is probably no project without changes in its database model after first deployment. Consequently, object model has to be change, too.
The best practice for database model changes is to create one or more SQL alter script which can be applied on your development computer(s) and afterward on your customer's server as well.
Updating object model in your .NET application is another story. Usually, developer has to carefully translate each change from underlying database model into application's object model. In multitier application architecture, developer has usually to update other layers of the application:
If code generation can create all or
most code for object-relational mapping classes and files, the same
technique can be used for updating object model if database model has
been changed.
This, in most projects iterative process, can be represented by the following simple diagram:

One of the major problems which have to be solved through the object model updating is to preserve the source code which has been changed or customized after the first code generation is used. Sometimes it's impossible to solve this problem completely, but if a solution can handle most of this work, it can save a lot of developer's time and reduces chances for creating many annoying bugs which emerges from mapping classes and/or NHibernate HBM Xml files.
Let's have a closer look about using NConstruct Builder in such cases.
Most of the source code NConstruct Builder generates is located in [your application name].Server project. Typical generated folder structure for the Server project looks like this in the picture:
If we focus on one table in the database model, for example - Shippers table, we can see there are four generated files in the Server project:
Information for generating those files is held in a Shippers table in the database model:

To support object model changes and to separate generated source code from your own code, NConstruct Builder takes advantage of one very useful .NET feature: partial classes. Where it's necessary or it might become necessary, NConstruct Builder generates two partial classes or at least insert a "Generated" keyword in the class' name.
First file, ShippersDTO.Generated.cs, is just a simple Data Transfer Object (or DTO, see also http://msdn.microsoft.com/en-us/library/ms978717.aspx" or http://en.wikipedia.org/wiki/Data_transfer_object).
As DTO pattern definition states, DTO class is used to transfer data between software application s).
As DTO pattern definition states, DTO class is used to transfer data between software application subsystems. DTO classes don't have any behavior except for storage and retrieval of its own data. NConstruct uses DTO classes for table-like data presentation (e.g. grid UI control). As DTO classes do not (and should not) have any business logic, there is no need to create two partial classes. NConstruct Builder doesn't create two files but it just adds a "Generated" keyword in the file's name and "partial" class definition.
For a data access layer based on NHibernate framework, two files per one mapping must be created. One of them is simple business object class, and another is NHibernate mapping file.
Without using the partial class feature, it would be enough to have two files in our Shippers table example: Shippers entity object class (e.g. ShippersEntity.cs) and Shippers NHibernate XML file (e.g. ShippersEntity.hbm.xml).
But as we saw, there is a possibility that someone would like to add some additional code in the object class. So, instead of one class, NConstruct Builder generates two classes:
|
namespace
Northwind.Server.Data.Northwind.Entity
{ public partial class ShippersEntity {} } |
This is the right place for a developer to add any additional methods or other custom code.
ShippersEntity.Generated.cs should therefore contain only generated code - only metadata information extracted from the database. If database model is changed, developer (or database administrator) applies SQL alter script on the database, run again code generation tool and overwrite or replace only generated files with the old ones. With such approach, all custom code in the data access layer remains intact whenever database model is changed.
NConstruct Builder has an option to generate only mapping and some other classes which might need updates if a database model is changed.
This feature can be combined with partial tables' selection in the Namespace definition step.

In this step, you may select only those tables, where your database has been changed. NConstruct Builder will however include related table(s) if you've changed their relations: table relations and their object's reflections are just as important part of object model as objects definitions are.
If you decide to generate only entity, DTO, action and some other classes after your database model is changed, use "Create entity, DTO, NHibernate *.Hbm.xml, Enumerations, Action, Resource *.resx, and Web Pages.xml files only" checkbox in the last step of NConstruct Builder wizard.

You may use the same project location value as your project is located, or, if you are not sure about changes you've made in your source code, you may use a different location and overwrite or merge files manually.
Difficulty level:easy
difficult
Prerequisites:
Let's add one new field in our database model. Assume we'd like to store fax number in a new field in Shippers table in the Northwind database.

SQL alter script for upgrading database would look like this one:
|
use Northwind go alter table Shippers add Fax varchar(50) null go |
To test NConstruct Builder doesn't destroy our programming work; add one dummy method in the ShippersEntity.cs class:
|
namespace Northwind.Server.Data.Northwind.Entity
|
Run NConstruct Builder and select only Shippers table in the Namespace definition step.

In the last step, tick the "Create entity, DTO, NHibernate *.Hbm.xml, Enumerations, Action, Resource *.resx, and Web Pages.xml files only" checkbox and leave the original project location value.

Click on the Finish button and wait for NConstruct Builder to generate new files.

Open generated Northwind solution again and check what is changed.
Generated DTO class has one new field (_Fax), one new property (Fax) and changed constructors according to the change in the database model:
|
... private String _Fax; public ShippersDTO(Int32 id, String companyname, String fax, String phone) : public ShippersDTO(Int32 id, String companyname, String fax, String phone, [VisibleAttribute, SortAttribute(1), RootPropertyName(ShippersEntity.FaxProperty)] |
Note: other, unchanged parts of the ShippersDTO.Generated.cs class source code are not shown in the code snippet above.
Generated entity class has one new field (_Fax), one new property (Fax) according to the change in the database model:
|
... private String _Fax; .... [VisibleAttribute, SortAttribute(1), FieldLengthAttribute(50), FilterableFieldAttribute] |
Note: other, unchanged parts of the tity.Generated.cs class source code are not shown in the code snippet above.
Generated NHibernate XML file has one new property definition according to the change in the database model:
|
<property name="Fax" column="Fax" access="field.pascalcase-underscore" not-null="false" type="System.String" insert="true" update="true"/> |
Note: other, unchanged parts of the ShippersEntity.hbm.xml file are not shown in the code snippet above.
Next thing to verify is our customized class, ShippersEntity.cs. It should still contain manually written method named SomeMethod().
|
namespace Northwind.Server.Data.Northwind.Entity
|
ShippersEntity.cs class is unchanged as it's meant to be.
Difficulty level: easy
difficult
Prerequisites:
In this case, we'll add a new table and create a relation to one existing table in our database model. Assume we'd like to add information about country for shippers: therefore we have to create Countries table with some basic fields and 1-M relation to the Shippers table.

SQL alter script for upgrading database would look like this one:
|
use Northwind go create table Countries ( go alter table Shippers add CountryID int null go alter table Shippers add constraint FK_Shippers_Countries foreign key (CountryID) references Countries (CountryID) go |
To test NConstruct Builder doesn't destroy our programming work; add one dummy method in the ShippersEntity.csclass:
|
namespace Northwind.Server.Data.Northwind.Entity
|
Run NConstruct Builder and select only Countries and Shippers tables in the Namespace definition step.

In the last step, tick the "Create entity, DTO, NHibernate *.Hbm.xml, Enumerations, Action, Resource *.resx, and Web Pages.xml files only" checkbox and leave the original project location value.

Click on the Finish button and wait for NConstruct Builder to generate new files.

Open generated solution again and check what's new and what's changed.
A new set of classes has been generated because we've added new table in the Northwind database:
| File name | Location | Purpose |
| CountriesEntity.Generated.cs | Northwind.Server\Data\Northwind\Entity | Generated entity class |
| CountriesEntity.cs | Northwind.Server\Data\Northwind\Entity | Empty partial class |
| CountriesEntity.hbm.xml | Northwind.Server\Data\Northwind\Entity | NHibernate mapping |
| CountriesDTO.Generated.cs/td> | Northwind.Server\Data\Northwind\DTO | DTO class for CountiresEntity |
| CountriesAction.cs | Northwind.Client\Presentation\Actions\Northwind | Menu action class |
However, if we want to find them in our solution, there's none of them. The reason NConstruct Builder doesn't do this automatically is the possibility of manual changes in the project file (Northwind.Server.csproj in this case) and problems with merging new and existing project file.
So, we have to add newly generated files to our projects manually. It's good to start with the core classes - those in the Northwind.Server project:




Generated DTO class has one new field (_CountryName), one new property (CountryName) and changed constructors according to the change in the database model:
|
... private String _CountryName; public ShippersDTO(Int32 id, String companyname, String countryName, String phone) : public ShippersDTO(Int32 id, String companyname, String countryName, String phone, [VisibleAttribute,
SortAttribute(1), ManyToOnePropertyAttribute(CountriesEntity.NameProperty), RootPropertyName(ShippersEntity.CountryProperty)] |
Note: other, unchanged parts of the ShippersDTO.Generated.cs class source code are not shown in the code snippet above.
Generated entity class has one new field (_Country), one new property (Country) according to the change in the database model:
|
... private CountriesEntity _Country; ... [VisibleAttribute, FilterableFieldAttribute, ManyToOnePropertyAttribute("Id", false)] public virtual CountriesEntity Country |
Note: other, unchanged parts of the ShippersEntity.Generated.cs class source code are not shown in the code snippet above.
Generated NHibernate XML file has one new many-to-one definition according to the change in the database model:
|
<many-to-one name="Country" access="field.pascalcase-underscore" not-null="false" outer-join="auto" insert="true" update="true"> |
Note: other, unchanged parts of the ShippersEntity.hbm.xml file are not shown in the code snippet above.
Next thing to verify is our customized class, ShippersEntity.cs. It should still contain manually written method named SomeMethod().
|
namespace Northwind.Server.Data.Northwind.Entity
|
ShippersEntity.cs class is unchanged as it's meant to be.
Application's source code modifications can be accomplished with the aid of NConstruct Builder when a database model changes. This process is fully automated within NConstruct Builder in simpler cases.
Some manual work in Visual Studio IDE for more complex cases can't be avoided, though.
NConstruct future versions might include more automation support for database changes. They will be described in "What's new" documents and in separate technical articles.