Click here to Skip to main content
Click here to Skip to main content

Business Objects for CodeSmith

By , 23 Nov 2004
 

Sample Image - BusnessObjectGenerator.gif

Introduction

One of the biggest issues a developer faces when developing a large application, is maintaining design standards and methods. Design documents, coding standards, and code review were the only tools a developer had to work with in the golden days of coding. With the birth of code generators such as CodeSmith, development teams are now armed with a powerful tool to expedite the development process and maintain a standard throughout the application. When developing applications, templates can save you a lot of time by using common design patterns for generating different business objects. By definition, templates are repeatable patterns, which can be derived from any design methods. The benefit of using templates in code generation is the ability to enforce design methods and standards while saving development costs for any application. This article will present a basic design pattern and the templates to generate code for the design pattern.

Business Object Design Pattern

Business objects contain properties that reflect data; you will find objects named invoice, invoice detail, etc. Commonly, they include embedded relationships -- for example, an invoice object may have a property that retrieves the details for that invoice instance.

Based on this simple observation, we can develop a design standard for our business objects:

  • Business Objects Contain Properties
  • Business Objects Require Collections
  • Business Objects Require Access Data

Business Object:

The Business Object Class Template (ClassGenerator.cst) is used to create a business object’s properties and methods. A standard set of methods for accessing the object's data will be generated for each object defined in an XML document. The following methods will be created for each business object defined:

Public Static Methods
  • CreateNewObject: Creates a new Object.
  • DeleteObject: Deletes an Object.
Public Instance Constructors
  • Object - Overloaded. Initializes a new instance of the Object class.
Public Instance Methods
  • Copy: Copies an Object.
  • Delete: Deletes an Object.
  • Fetch: Fetches an Object.
  • Save: Saves an Object.
  • Update: Updates an Object.

Business Object Collection:

The Business Object Collections Template (CollectionGenerator.cst) is used to create a collection class for each business object. The collection object uses the 'CollectionBase' as the base class. The following methods will be created for each business object defined:

Public Instance Constructors
  • ObjectCollection: Constructor initializes a new instance of the ObjectCollection class.
Public Instance Properties
  • Count: Gets the number of elements contained in the CollectionBase instance.
  • Item: Gets or sets the value associated with the specified key.
Public Instance Methods
  • Add: Adds an item to the Object Collection.
  • Contains: Determines whether the Object Collection contains a specific Object.
  • IndexOf: Determines the index of a specific item in the Object Collection.
  • Insert: Inserts an item to the Object Collection at the specified position.
  • Remove: Removes the first occurrence of Object in the Object Collection.
Protected Instance Methods
  • OnInsert: Validates before inserting a new Object into the Object Collection.
  • OnRemove: Validates before removing a new Object from the Object Collection.
  • OnSet: Validates before setting an Object in the Object Collection.
  • OnValidate: Performs additional custom processes when validating an Object.

Business Object Data:

The Business Object Data Class Template (DataClassGenerator.cst) is used to define the data access layer for each business object. The following methods will be created for each business object defined:

Public Instance Constructors
  • ObjectData: Constructor initializes a new instance of the ObjectData class.
Public Instance Methods
  • CreateNewObject: Creates a new Object in the database.
  • DeleteObject: Deletes an Object from the database.
  • FetchObject: Gets a single Object from the database.
  • UpdateObject: Updates an Object in the database.

Base Object Classes:

The Business Object Base Class Template (BaseObjectClass.cst) is used to create the base class for each business object. The following are the properties used for each business object:

Public Instance Properties
  • Id: ID of Business Object.
  • Name: Name of Business Logic Object.
Internal
  • GenerateObjectId: Generates an ID for the given object.

Base Object Data Class

The Business Object Base Data Class Template (BaseDataClass.cst) is used to create the base class for each business object. The following are the properties used for each business object:

Public Instance Constructors
  • BaseDataClass: Constructor initializes a new instance of the BaseDataClass class.
Public Instance Properties
  • ConnectionString: Gets Connection String configuration from a config file.
Public Instance Methods
  • AddParamToSQLCmd: Adds a parameter to a SqlCommand.
  • ExecuteCollectionReader: Returns an object collection from a SQL Data Reader.
  • ExecuteObjectReader: Returns an object from a SQL Data Reader.
  • ExecuteReaderCmd: Generates Object Collection from SQL Data Reader.
  • ExecuteScalarCmd: Executes a query.
  • SetCommandType: Sets the CommandText property to the name of the stored procedure.

Data Layer Generator:

The Data Layer Template (DataGenerator.cst) is used to create the required database objects needed to support the business objects.

Procedures
  • Object_Create: Creates a new Object in the database.
  • Object_Delete: Deletes an Object from the database.
  • Object_Fetch: Gets a single Object from the database.
  • Object_Update: Updates an Object in the database.

Using the Generator

Based on a definition provided by an XML Document, the generator will produce code for your business object, business object collection, business object data access, business object tables, and stored procedures.

Business Objects Attributes

attribute

maps to

remarks

class

table

name will represent the table name

property

column

name will represent the column name

Class Attributes

attribute

remarks

name

represents the table name

Property Attributes

attribute

remarks

name

represents the column name

type

represents a system type or a business object collection

maxSize

 
Supported Types

C# Type

Maps to SQL type

string

nvarchar

int

int

DateTime

smalldatetime

bool

bit

decimal

money

Defining the Business Objects:

Let's create a simple Invoice Business Object. The invoice object will contain a customer name, invoice date, invoice paid status, and line items. The following XML document defines the objects:

<?xml version="1.0" encoding="utf-8" ?> 
<BusinessObjects xmlns="http://www.austinconnergroup.com">
  <class name="Invoice">  
    <properties>
      <property name="Id" type="String" maxSize="36" />
      <property name="Customer" type="String" maxSize="96" />
      <property name="InvoiceDate" type="DateTime" maxSize="" />
      <property name="InvoicePaid" type="bool" maxSize="" />
      <property name="InvoiceDetails" type="InvoiceDetailCollection" maxSize="" />
    </properties>
  </class>
  <class name="InvoiceDetail">  
    <properties>
      <property name="Id" type="String" maxSize="36" />
      <property name="InvoiceId" type="String" maxSize="36" />
      <property name="LineItem" type="Int" maxSize="" />
      <property name="ItemDescription" type="String" maxSize="96" />
      <property name="ItemCostPerUnit" type="Single" maxSize="" />
      <property name="ItemQuanity" type="Int" maxSize="" />
      <property name="ItemUnit" type="String" maxSize="8" />
    </properties>
  </class>
</BusinessObjects>

In our definition document, we define two objects, Invoice and InvoiceDetail. You will notice that the Invoice object contains a property InvoiceDetails which is of the type InvoiceDetailCollection. This defines a relationship between InvoiceDetail and Invoice, and will produce the required methods and SQL statements for this relationship.

Running the Generator

Once we have our model, we are ready to generate our code. BuildTemplate.cst is the main entry point for generating the code for all the business objects, and has the following properties:

  • XmlFile - XML Document that the classes will be generated from.
  • OutputDirectory - The base directory for code output.
  • GenerateBaseClasses - Set true to generate base classes.
  • RootNamespace - The root namespace generated classes will be a member of.
  • ObjectNamespace - The object namespace generated classes will be a member of.
  • BusinessLogicNamespace - The business object namespace generated classes will be a member of.
  • DataAccessNamespace - The data object namespace generated classes will be a member of.
  • DeveloperName - Developer's name.
  • CompanyName - Company name.

Points of Interest

The article here presents the prototype that I developed for proof of concept. After writing the generator and supporting templates, I was so amazed at the results, I immediately wrote the templates for our team and deployed them into our production environment. One of the biggest benefits was not the cost savings in time, but the fact that all the generated code was self documenting. This fact alone was worth the efforts in creating these templates. The biggest battle I faced everyday was the lack of documented code, now it's a snap.

History

  • 11/23/2004 - Initial article.

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)

About the Author

JR Hull
Web Developer
United States United States
Member
Software Architect with 20++ years of software design and development experience with a strong hold in Object-Oriented software engineering using UML with Design Patterns. Architected and developed several industrial software packages and passed through full software development life-cycle. Currently managing a small group of developers, developing management software for the agriculture industry.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralError when use templatememberdaica198112 Aug '09 - 22:54 
i have an error when execute any template, help me please
 
---------------- Compile started -----------------
 
c:\ProgramData\CodeSmith\v5.1\Template Cache\-815104299\BaseDataClass_cst.cs(22,26): error CS0012: The type 'CodeSmith.Engine.CodeTemplate' is defined in an assembly that is not referenced. You must add a reference to assembly 'CodeSmith.Engine, Version=2.5.14.0, Culture=neutral, PublicKeyToken=9fd61cdb91609a7a'.
 
Build complete -- 1 errors, 0 warnings
 
---------------------- Done ----------------------
 
Build failed
GeneralRe: Error when use templategroupACG10019917 Aug '09 - 4:02 
The assembly must exist in the Global Assembly Cache, in the same directory as CodeSmith, in the CodeSmith\bin directory, or in the CodeSmith\AddIns directory. If you're working with templates within CodeSmith Studio, the preferred location is the CodeSmith\AddIns directory.
 
J.R. Hull
GeneralFailed Usingmemberasmaashafeik12 Feb '08 - 2:15 
I'm using codsmith Version=4.0. How can i use these templates?
Not:
When trying to use them I got this message:
<b>Error loading assembly CodeSmith.Engine, Version=2.5.14.0</b>, Culture=neutral, PublicKeyToken=9fd61cdb91609a7a.   Please make sure that you re-compile any custom assemblies against the current version of CodeSmith.
 
System.IO.FileLoadException: Could not load file or assembly 'CodeSmith.Engine, Version=2.5.14.0, Culture=neutral, PublicKeyToken=9fd61cdb91609a7a' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
File name: 'CodeSmith.Engine, Version=2.5.14.0, Culture=neutral, PublicKeyToken=9fd61cdb91609a7a'
   at System.Reflection.Assembly.GetType(String name, Boolean throwOnError, Boolean ignoreCase)
   at CodeSmith.Engine.CodeTemplateCompiler.CreateInstance()
   at CodeSmith.Gui.CodeTemplateGenerator.a(String A_0, String A_1, String A_2, Boolean A_3, Boolean A_4)
 
WRN: Assembly binding logging is turned OFF.
To enable assembly bind failure logging, set the registry value [HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD) to 1.
Note: There is some performance penalty associated with assembly bind failure logging.
To turn this feature off, remove the registry value [HKLM\Software\Microsoft\Fusion!EnableLog].
Generalfailed usingmemberasmaashafeik12 Feb '08 - 1:24 
I tried to use these template but when compiled usig codsmith stduio i got this message.
WRN: Assembly binding logging is turned OFF.
To enable assembly bind failure logging, set the registry value [HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD) to 1.
Note: There is some performance penalty associated with assembly bind failure logging.
To turn this feature off, remove the registry value [HKLM\Software\Microsoft\Fusion!EnableLog].
GeneralFailed using CodeSmith V3.0memberSonnyKei20 Jul '05 - 15:57 
I have downloaded version 3.0. I managed to load the BusnessObjects_1_0.sln in Visual Studio (1.1) and recompiled it. I excluded the Sample Tester project out since I was getting problems loading it. I copied the DLL into the CodeSmith Templates directory (same level as the BusnessObjects_1_0 directory). But, when I load the any of templates in the CodeSmith (using File-Open), I am unable to run it. The property window is showing blank.
 
It underlines the <%@ Assembly Name="BusnessObjects.Templates" %> at the 2nd line saying “Unable to resolve the assembly BusnessObjects.Templates”
 
Does anyone have these templates for VB.net?

GeneralRe: Failed using CodeSmith V3.0memberJR Hull12 Oct '05 - 3:54 
The assembly must exist in the Global Assembly Cache, in the same directory as CodeSmith, in the CodeSmith\bin directory, or in the CodeSmith\AddIns directory. If you're working with templates within CodeSmith Studio, the preferred location is the CodeSmith\AddIns directory.
 
J.R. Hull

GeneralRe: Failed using CodeSmith V3.0membercuiyang12311 Apr '06 - 6:20 
http://community.codesmithtools.com/forums/9450/ShowThread.aspx[^]
 
Hope this helps.
GeneralA note on business objectsmembernedcod10 Feb '05 - 21:08 
Nice article. I have one comment though Smile | :)
 
Business objects, in my opinion and understanding, are objects that map the "real world" (read: business). A simplified example might be an Invoice -it might consist of a delivery address and the individual products bought.
 
Your Invoice class in turn might then contain two objects - an address object and a collection of product objects.
 
If you use a traditional relational database model (which I'm sure most companies still use) you would typically normalize your database to have the Invoice ID (primary key) and possibly the address in one table and your Invoice Product info in another (linked with the invoice id).
 
Now, if you generate your Business Objects from this database, you'll just be modeling your data - and not the object - thereby missing the whole point of OO.
 
I suppose you could set up views to mirror your objects, and then generate them off these views, but given deadlines, budgets etc, having that extra layer might not be cost-effective.
Or alternatively have an Object-SQL DBMS.
 

 

GeneralRe: A note on business objectssussAnonymous25 Jul '05 - 23:41 
As taught by most Unies... However if you are designing a large or distributed system it is best to keep a 1:1 relationship between your classes and data.
 
Also there is nothing to stop this being a good OO design. ie
There is nothing wrong with having an Invoice Class like this
Invoice
Address customs
LineItem[] lineItems
 
You are still modelling real world objects , and keeping your data with your logic which are the key points to OO!
 

 
Ben

GeneralVB version of Editor property attributememberBill_Philly16 Dec '04 - 5:55 
Nice article, thanks.
 
I'm fairly new to Codesmith and property editors so I wasn't sure what I needed to try an example in VB.
 
This article mentions creating a usercontrol, but it appears we don't need for file selection...
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndotnet/html/vsnetpropbrow.asp[^]
Here's the VB version for the xmlfile: (extra angle at beginning since not sure how to avoid html processing)
<<CodeTemplateProperty(CodeTemplatePropertyOption.Required), Category("Source Table"), _
Editor(GetType(System.Windows.Forms.Design.FileNameEditor), GetType(System.Drawing.Design.UITypeEditor)), _
Description("Required - The XML Document that the output will be generated from.")> _
Public Property XmlFile As string
Get
Return mXmlFile
End Get
Set(ByVal Value As String)
mXmlFile = Value
End Set
End Property
 

Bill

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130523.1 | Last Updated 23 Nov 2004
Article Copyright 2004 by JR Hull
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid