Concepts - Templates and Template groups

Preface

LLBLGen Pro ships with two template based code generators: CodeEmitter and DotNetTemplateEngine. CodeEmitter (located in the SD.LLBLGen.Pro.TaskPerformers.dll) is a template based code emitter which consumes templates written in TDL (Template Definition Language). TDL is LLBLGen Pro's own template language. DotNetTemplateEngine (located in the SD.LLBLGen.Pro.LptParser.dll) is a template based code emitted which consumes templates written in either the .NET language C# or VB.NET. Written in means the template logic is written in that language. The text which forms the output of the code generators can be in any format. The code generators are so called Task performers, which are able to perform a task as described in Concepts - task based code generation.

To work correctly the code generators consume templates which are normal textfiles. Because the task performers are specified in template independent .tasks files, they use template ID's to identify which template to use for the execution of the code generator. Which file is bound to the template ID specified in so called template bindings files, which have the extension .templatebindings, and are located in the Templates folder.

Templates

LLBLGen Pro uses two kinds of templates: generic templates, or shared templates, and database specific templates. As discussed above, templates are identified by the Template ID they're bound to. A template ID can have multiple files bound to it, one per target language, per .templatebindings file. This means that you can define your own bindings in a separate .templatebindings file, to overrule a shipped binding definition. As the template ID is target language independent and also template file independent, you can use the task performers with any set of templates available.

For example, when the CodeEmitter is executed it looks up the template ID, which is specified as a parameter of the task, in the list of template bindings defined. If found, it will load the bound template file and use that template as the one to work with. To learn more about using template bindings during code generation configuration, please see Designer - Generating code, tab 2.
Template files
A template file is a code file with the code that should be emitted in the file it is the template for (e.g. a template for an entity class). If it's a template which comes with LLBLGen Pro, it has the extension .template and it contains template logic based on the TDL language and is used by the CodeEmitter task performer. The TDL drives the CodeEmitter to create the output requested, for example loop through object lists or simply emit a piece of information like the name of the current entity into the output. TDL statements are not built on top of an existing language, and are solely meant for code emitting using LLBLGen Pro. For an in-depth discussion about TDL, how to create your own templates and other details related to the templates in LLBLGen Pro, please see the LLBLGen Pro SDK, which is a free download for LLBLGen Pro customers.

Included template files

LLBLGen Pro ships with two groups of template files: "SelfServicing" and "Adapter". All templates of these groups are either contained in one template directory per driver (the driver specific templates, e.g. SqlServerSpecific) or the SharedTemplates folder, all located in the Templates folder in the LLBLGen Pro installation folder. SelfServicing and Adapter templates are stored in the same folder since some template files are shared among the two template groups. Each template group generates code which is different in style, functionality and paradigm from the other. Which template group to use is selected by the template group combo box on the first tab in the generator configuration window. Per template group you can have different scenario's, like 'General' and 'Two classes', which can be selected by picking the right preset in the third tab of the generator configuration window.

Below are short descriptions of the template groups' typical aspects, so you can better decide which template group to choose for your project.
SelfServicing
SelfServicing is the template group which was initially shipped with LLBLGen Pro and it's named SelfServicing because the entity, typed list and typed view classes contain all the logic and data to help themselves interacting with the persistent storage. This means that there is no extra object instance required, like a broker, to fetch entity data from the persistent storage or save data into the persistent storage. This can be very handy if you don't want to be bothered with the hassle of extra objects to fetch data related to an instance you hold or you want to traverse relations like myCustomer.Orders[0].Products[0].ShipperName in a class that potentially doesn't have database access like a gui. This traversal fetches data on the fly with lazy loading (load on demand) using logic that is controlled by code inside the entities itself: the entities instantiate the required DAO objects to retrieve the data and to instantiate the related objects. This is transparent for the developer and is easy to use.

The presence of persistence logic inside the entity, typed list and typed view classes can in, some situations, be a disadvantage of the SelfServicing code. For example if you as a project manager do not want to have your GUI developers call myEntity.Save(), you have to add extra code to the generated classes to prevent any save action from happening and even then, the logic is exposed to the developer. The template group called Adapter solves this. In short, SelfServicing is about the paradigm that object persistence is something about the objects being persisted, so an entity object should know how to persist itself. SelfServicing's code is generated for one database type (e.g. Sqlserver / Oracle).

An example piece of SelfServicing code is the following. This code reads an Order entity from the persistent storage, alters its EmployeeID field and saves it back.
// C#
OrderEntity myOrder = new OrderEntity(10254);
myOrder.EmployeeID = 6;
myOrder.Save();
' VB.NET
Dim myOrder As New OrderEntity(10254)
myOrder.EmployeeID = 6
myOrder.Save()

SelfServicing comes in two variants: General and TwoClasses. The General variant, formulated in the General preset ( See: Concepts - task based code generation) generates one class per entity. The TwoClasses variant generates two classes per entity: entityNameEntityBase, which contains the generated plumbing code and entityNameEntity, which derives from that class and which is for your business logic.
Adapter
Adapter is called Adapter because all persistence actions are performed by an 'Adapter' object, similar to the DataAdapter in .NET. Adapter's entities don't have persistence information, nor do they contain persistence action logic. Because it uses adapter objects, called DataAccessAdapter, you can choose the adapter you want to use to persist the entity object when you actually need it. Adapter uses a single point where the persistence data is stored, hidden away from the developer. The DataAccessAdapter itself has access to the persistence information in code, which is at runtime constructed in a cache with persistence info objects.

Adapter's generated code is not 'selfservicing', which means that you have to pull data from the database up front or consult a DataAccessAdapter object to read data again later because there is no logic inside the entity objects to control persistence actions like reading related entities from the database through lazy loading. This can be perfect for projects where it is mandatory that every database action is started and controlled by a selected piece of code, for example a selected set of Business Logic classes in a middle tier. It can however be a bit cumbersome for projects where selfservicing aspects of an entity should be utilized. It is therefore important to understand how you look at what persistence of objects means to your code.

Adapter is about the paradigm that persistence is a 'service' provided by an object or group of objects and which is provided by logic outside the objects affected by the service. As an illustration of this, the same functionality provided as an example with the SelfServicing explanation above is written using the Adapter logic:
// C#
OrderEntity myOrder = new OrderEntity(10254);
DataAccessAdapter adapter = new DataAccessAdapter();
adapter.FetchEntity(myOrder);
myOrder.EmployeeID = 6;
adapter.Save(myOrder);
' VB.NET
Dim myOrder As New OrderEntity(10254)
Dim adapter As New DataAccessAdapter()
adapter.FetchEntity(myOrder)
myOrder.EmployeeID = 6
adapter.Save(myOrder)

Adapter requires more lines of code when fetching data, however it also gives more control over the steps taken, for example it allows you to specify whether the connection should stay open so actions taken after the current action will be faster, because an open connection is already available (the connection is closed otherwise after each action), or which connection string to use for this particular action. It is therefore key to first determine what kind of paradigm you want to use before generating code.

Adapter also comes in two variants: General and TwoClasses. The General variant, formulated in the General preset ( See: Concepts - task based code generation) generates one class per entity. The TwoClasses variant generates two classes per entity: entityNameEntity, which contains the generated plumbing code and MyentityNameEntity, which derives from that class and which is for your business logic. Users of LLBLGen Pro v1.0.200x.y are likely familiar with the 3rd party add-on 'AdapterExtendedEntityTemplates'. The TwoClasses variant is this add-on, but now included in the standard templates shipped with LLBLGen Pro.

All template groups are fully supported and have the same basic persistence options, however one template group can have more sophisticated persistence options than the other while the other template group might have more functionality on board for ease of use.

When to use which template group?
Both template groups offer a wide set of functionality, but do that in a different way. This difference makes it important for you to know when to pick which template group for a given project. Below are two short lists which sum up some reasons for choosing each template group and which will help you with the decision which template group to take.

When to use SelfServicing

When to use Adapter

LLBLGen Pro v2.6 documentation. ©2002-2008 Solutions Design