Template Sets - Template Definition Language (TDL)
The LLBLGen Pro templates used to generate the generated code for you, are defined in a special language: the Template Definition Language or TDL. The language is used to define areas in normal program code which are to be used by the TDL Parser. TDL templates are stored in files with the extension .template and are interpreted by an interpreter.
Starting with v4.0 the TDL interpreter/parser have been frozen: no new functionality will be added, they'll only be adjusted to match changes in the LLBLGen Pro designer assemblies so the TDL interpreter works properly. This means that there's no functionality added for Table Valued Functions.
From v4.0, it's recommeneded to write all templates using the .lpt system. To get started with the .lpt system, it's recommended to check out the various .lpt templates shipped with LLBLGen Pro. You can include .lpt templates inside TDL templates, however be aware that lpt template logic can only be written in C# (template output can be any language)
The TDL interpreter/parser won't be removed from the system in the future, they just won't receive new updates to support new functionality in the designer.
TDL itself is a simple language, with 2 constructs and various 'tags' which represent a value in the current context. TDL is a pattern matching language, which means that it doesn't contain the ability to specify expressions. The reason for this is that the language itself is very easy to use and doesn't cause a lot of syntax errors in TDL statements.
If the token found is not understood or not well formed, it is skipped as a token and seen as part of the text the tokens are placed in. This means you can find errors very easily: the tokens which are wrong are emitted in the generated code, because what's not recognized as a token or is an erroneous statement, is seen as plain text and is emitted directly into the destination file.
Changes starting with v4
The TDL parser and interpreter have been frozen. No new features have been added. This means that Table Valued Functions are not available through TDL statements.
Removed / changed statements starting with v3
The following section is only interesting if you're coming from v2.x and have templates written in v2's TDL. The following statements have been removed or changed starting with v3. When porting templates over from v2.x to v5, please make sure you adjust your templates so they don't contain statements which are removed or with wrong parameters.
- SubTypeFieldIndex, SuperTypeFieldIndex and IndexFirstNonInheritedField are removed. These statements are removed from the interpreter and will throw an exception. They should be replaced by proper fieldindex enum usage which are casted to int as is done with the discriminatorcolumn.
-
CatalogName has been removed. The
<[CatalogName]>
statement is no longer useful and has been removed. - Foreach FieldToLink has been removed. The loop statement Foreach FieldToLink has been removed as it is of no longer use. The loop is only used to provide fieldindexes for the PK fields in a type which is in a TargetPerEntity.
- Foreach RelatedHierarchyEntity loop has been removed. The loop statement foreach relatedhierarchyentity has been removed as it's not really useful anymore because the inheritance edges are not stored as relationships. The loop is also overkill as there's always at most 1 edge, the one with the supertype (if applicable), and the outcome is always the same: a 1:1 pk-pk relationship. As in v3.0, subtypes inherit the PK of the supertype, the fieldnames are already known, so the code is pretty straight forward: for each pk field, a pair with subtype-supertype names has to be emitted if the subtype is in a targetPerEntity and the supertype is too. To grab all subtypes of a type, a new statement is introduced, Foreach SubType
- If HasPrimaryKey lost its IncludeInherited attribute. The attribute was not used.
- Foreach PrimaryKeyEntityField lost its IncludeInherited attribute. As an entity always inherits the PK of its supertype, either there is a PK or there's not a PK whatsoever. IncludeInherited therefore is of no use.
- If EntityFieldOverrides/EntityFieldIsOverriden have been removed. Starting with v3.0 there are no possibilities to override a field in a subtype of an entity for the simple fact that it makes no sense from a mapping's point of view: it's ambiguistic. It also only occurred for PK fields in v2.x anyway, so it can be replaced with If IsSubtype, and if so it should emit override/overrides and otherwise virtual. EntityFieldIsOverriden can also be replaced with its current companion If EntityFieldContainedInCurrentEntity (negated) which already does all the work.
- If IsOnSubtypeSide has been removed. Due to changes in how hierarchy relationships are emitted into the generated code, this statement has become obsolete and has been removed.
- If OppositeRelationPresent's meaning has changed and has lost its 'full' argument. It's no longer possible to hide a relationship from one side. This statement returns now true only if the other side's navigator is not empty. The 'Full' argument is therefore not used anymore and removed.
- If RelationIsHidden has been removed. Relationships can't be marked as hidden anymore so this statement is of no use anymore.
- Foreach CustomProperty elementtype has now a different set of elementtype values. The values accepted are equal to If SettingValueEquals, and the backwards compatibility arguments: EntityField, ActionStoredProcedureCall and RetrievalStoredProcedureCall.
- Foreach EntityField now has a new argument: IncludeInheritedPk. This argument, IncludeInheritedPk, will cause the inherited primary key field(s) to be included in the loop, at the front (as inherited fields are always at the front), if the current entity is a subtype and in a TPE inheritance hierarchy. Otherwise this argument has no effect. Can not be specified with IncludeInherited combined, only one can be specified.
- If HideFromDatabinding has been removed. If HideFromDatabinding is no longer necessary as starting with v3.0 LLBLGen Pro implements a proper attribute generation system. This replaces this statement as there's no need for it anymore: the only attribute it hid is now emitable easily or disabled easily through the project's attributes (or enabled easily on a per element basis)
To migrate changes made to shipped templates, it's key to migrate changes to the v5 shipped templates, instead of migrating altered v2.x templates to v5. Also, please consider migrating changes only if the designer doesn't facilitate in adding things automatically, e.g. it's not necessary anymore to alter templates to add custom attributes to generated members / classes.
Grammar
The grammar is kept simple. All tokens are placed between <[
and
]>
characters and are case insensitive. There are 2 constructs
defined: If
expression EndIf
and Foreach
expression NextForeach
.
These statements work on different elements inside the current project
definition and can be nested indefinitely, however two of the same loop
statements will work on the same global element. The If
and Foreach
constructs are the only constructs which are not 'replaced' by the data
they represent, but are used to emit 0 or more times the text inside
them.
Foreach
has several optional parameters to format the code
generated and If
has optional parameters to for example perform an If Not
expression or test on a selective part of the project.
The interpreter has a list of 'current elements' which are valid and used in the scope of the current construct, which is a list of references to all kinds of objects which are currently the 'current' for that particular construct.
These lists are reset at the beginning of a new template. If you nest two entity loops inside each other, the inner loop will mess with the outer loop's current entity value for example, because both operate on the same current element. This is by design, since the tokens are not defined to form a generic language, but a language dedicated to generate code from entities.
Also, if there is no current value (e.g. you start an entity field loop but there is no current entity), the interpreter will skip the loop.
The TDL statements can be grouped together in several groups:
- Single token statements, which are the majority of the statements, they simply are replaced by the value(s) they represent
- Name single token statements, which are single token statements but reflect a name like the name of the current entity. You can set casing for these statements.
- Miscellaneous statements various statements which require 0 or more parameters and perform various actions like casing.
- Loop statements, which are the various Foreach loops
- If statements, which are the various If expression EndIf blocks
The various statements are described per group briefly. Optional tokens
are stated in italic, mandatory tokens are stated in bold. When
you see a formulation like <[CaseCamel NameSingleTokenStatement]>, it means NameSingleTokenStatement is
one of the Name single token statements, but without the <[
and
]>
characters, for example <[CaseCamel EntityFieldName]>
.
When one of a series of choices is possible, these choices are separated
by a |
character, for example CursorsOnly|NoCursors
.
Single token statements
Token | Description |
---|---|
<[ActualParameterName]> |
Will be replaced by the name of the stored procedure parameter as it is defined in the stored procedure definition of the current stored procedure call. Used inside currentSPParameter affecting loops. |
<[ActualStoredProcedureName]> |
Will be replaced by the name of the stored procedure as it is defined in the stored procedure definition of the current stored procedure call. Used inside Foreach ActionStoredProcedureCall or Foreach RetrievalStoredProcedureCall loops |
<[AggregateFunction]> |
Will be replaced by the aggregate function defined for a typed list field. |
<[AmountOfEntityFields]> |
Will be replaced by the amount of fields in the current entity. This is without inherited fields. |
<[AmountOfParameters]> |
Will be replaced by the amount of parameters defined in the current stored procedure call. Used inside Foreach ActionStoredProcedureCall or Foreach RetrievalStoredProcedureCall loops |
<[AmountOfTypedListFields]> |
Will be replaced by the amount of fields in the current typed list. Used inside Foreach TypedList loops |
<[AmountOfTypedViewFields]> |
Will be replaced by the amount of fields in the current typed view. Used inside Foreach TypedView loops |
<[ArrayIndexOperator]> |
Will be replaced by the text defined as arrayIndexOperatorOpenChar and arrayIndexOperatorCloseChar in the template config file. |
<[Attribute]> |
Will be replaced by the current Additional Attribute definition inside a Foreach Attribute loop |
<[ConnectionString]> |
Will be replaced by the connection string used to create the project. |
<[ConnectionStringKeyName]> |
Will be replaced by the name for the connection string element, as specified with the pattern in the project properties |
<[CurrentAdditionalInterface]> |
Will be replaced by the current additional interface, with all the macros processed. Used inside Foreach AdditionalInterface loops. |
<[CurrentAdditionalNamespace]> |
Will be replaced by the current additional namespace, with all the macros processed. Used inside Foreach AdditionalNamespace loops. |
<[CurrentParameterDirection]> |
Will be replaced by the direction of the current parameter, and is one of the values for the ParameterDirection enum. Used inside Foreach InputParameter, Foreach OutputParameter or Foreach Parameter loops. |
<[CustomPropertyName]> |
Will be replaced by the name of the current custom property. Used inside Foreach CustomProperty argument loops. Newlines are converted to \n, quotes are escaped. |
<[CustomPropertyValue]> |
Will be replaced by the value of the current custom property. Used inside Foreach CustomProperty argument loops. Newlines are converted to \n, quotes are escaped. |
<[DbSpecificNamespaceSuffix]> |
Adapter specific TDL statement which is replaced by '.' + the value of the ProjectProperties.AdapterDbSpecificProjectFileSuffix value, or nothing if that value is empty. |
<[Description]> |
Will be replaced by the description specified for the current field (entity, valuetype, typedview) or current parameter. |
<[DiscriminatorColumnName]> |
TDL statement which is replaced by the name of the discriminatorcolumn of the current entity, if the entity is in a TargetPerEntityHierarchy inheritance hierarchy. |
<[DiscriminatorValue]> |
TDL statement which is replaced by the value, to use for distinguishing an entity in a TargetPerEntityHierarchy. The value can be a numeric value, a GUID or a string. If it's a string, it will be surrounded by "" automatically. If it's a GUID, it will automatically be generated as a constructor call to System.Guid. |
<[ElementTargetCatalogName]> |
This statement returns the catalog name of the target of the current element. Element can be entity, typedview or stored procedure call |
<[ElementTargetSchemaName]> |
This statement returns the schema name of the target of the current element. Element can be entity, typedview or stored procedure call |
<[ElementTargetObjectName]> |
This statement returns the object name of the target of the current element. Element can be entity, typedview or stored procedure call |
<[EndEntityAlias]> |
Will be replaced by the alias for the end entity in a relation in a typed list. A typed list always defines an alias for every entity in the typed list, however this alias could be empty (default), thus the empty string. |
<[EntityAlias]> |
Will be replaced by the alias for the entity the current typed list field belongs to. |
<[FieldCaption]> |
Will be replaced by the name for the typedview/typedlist field, which can be used by the developer at runtime. |
<[FieldIndex]> |
Will be replaced by the current index of the loop it is used in. This is equal to the ForeachIndex-1, as the ForeachIndex is 1 based and this index is 0 based. Used inside Foreach EntityField, Foreach TypedListField or Foreach TypedViewField loops. |
<[FieldMaxLength]> |
Will be replaced by the max-length value of the current field (valuetype, entity, typedview) in scope |
<[FieldPrecision]> |
Will be replaced by the precision value of the current field (valuetype, entity, typedview) in scope |
<[FieldScale]> |
Will be replaced by the scale value of the current field (valuetype, entity, typedview) in scope |
<[ForeachIndex]> |
Will be replaced by the current iteration of the Foreach loop this statement is placed in. |
<[IdentityValueSequenceName]> |
Will be replaced by the name for the sequence to use for the current Entity Field, which is an identity field. Used in loops which affect the currentEntityField element |
<[IsIdentity]> |
Will be replaced by the trueKeyword or the falseKeyword, based on the value of IsIdentity of the current entityfield. The trueKeyword and falseKeyword are defined in the template config file. Used in loops which affect the currentEntityField element. |
<[IsForeignKey]> |
Will be replaced by the trueKeyword or the falseKeyword, based on the value of IsForeignKey of the database field the current entityfield is mapped on. The trueKeyword and falseKeyword are defined in the template config file. Used in loops which affect the currentEntityField element. |
<[IsNullable]> |
Will be replaced by the trueKeyword or the falseKeyword, based on the value of IsNullable of the current entityfield. The trueKeyword and falseKeyword are defined in the template config file. Used in loops which affect the currentEntityField element. |
<[IsPrimaryKey]> |
Will be replaced by the trueKeyword or the falseKeyword, based on the value of IsPrimaryKey of the current entityfield. The trueKeyword and falseKeyword are defined in the template config file. Used in loops which affect the currentEntityField element. |
<[IsReadOnly]> |
Will be replaced by the trueKeyword or the falseKeyword, based on the value of IsReadOnly of the current entityfield. The trueKeyword and falseKeyword are defined in the template config file. Used in loops which affect the currentEntityField element. |
<[JoinHint]> |
Will be replaced by the the hint to use for the relation specified in a typed list. Is a value of the JoinHint enum definition. |
<[LazyLoadingWithoutResultReturnsNew]> |
Will be replaced by the true keyword defined in the templateset config if the project properties have the property LazyLoadingWithoutResultReturnsNew set to true, otherwise the false keyword. Used to set _entityReturnsNewIfNotFound flags in selfservicing entity classes. |
<[LLBLGenVersion]> |
Will be replaced by the current version of LLBLGen Pro which was used to start the code generator. |
<[ParameterIndex]> |
Will be replaced by the index of the current parameter in the list of parameters of the current stored procedure call. Index is 0 based. Used inside currentSPParameter affecting loops |
<[ParameterPrecision]> |
Will be replaced by the precision of the current stored procedure parameter. Used inside currentSPParameter affecting loops |
<[ParameterScale]> |
Will be replaced by the scale of the current stored procedure parameter. Used inside currentSPParameter affecting loops |
<[ParameterSize]> |
Will be replaced by the size of the current stored procedure parameter. Used inside currentSPParameter affecting loops |
<[ProcedureOutputType]> |
Will be replaced by the DataSet if the current stored procedure has more than 1 resultset, otherwise DataTable. Used in SqlServer templates, because SqlServer stored procedures can return multiple resultsets without cursors. Not used in Oracle templates for that reason. Used inside currentSPCall affecting loops. |
<[RootNamespace]> |
Will be replaced by the specified Root namespace in the generator configuration screen. |
<[SourceColumnCatalogName]> |
Will be replaced by the catalog name the object of the sourcecolumn is located in. Used in currentEntityField / currentTypedViewField affecting loops |
<[SourceColumnDbType]> |
Will be replaced by the DB Provider specific type specification of the database type of the current mapped field, it will be the enum value of for example SqlDbTypes. Used in currentEntityField affecting loops |
<[SourceColumnIsNullable]> |
Will be replaced by the trueKeyword or the falseKeyword, based on the value of IsNullable of the current entityfield. The trueKeyword and falseKeyword are defined in the template config file. Used in loops which affect the currentEntityField element. |
<[SourceColumnMaxLength]> |
Will be replaced by the maximum length (the size) of the field mapped onto the current entity field. Used in loops which affect the currentEntityField element. |
<[SourceColumnPrecision]> |
Will be replaced by the precision of the field mapped onto the current entity field. Used in loops which affect the currentEntityField element. |
<[SourceColumnScale]> |
Will be replaced by the scale of the field mapped onto the current entity field. Used in loops which affect the currentEntityField element. |
<[SourceColumnName]> |
Will be replaced by the name of the field mapped onto the current entity field. This field is not a Name statement, because it shouldn't be affected by case statements for case sensitive installations of the database system. Used in loops which affect the currentEntityField element. |
<[SourceObjectName]> |
Will be replaced by the object name the field mapped onto the current entity field belongs to, typical a table. Used in loops which affect the currentEntityField element. |
<[SourceSchemaName]> |
Will be replaced by the schema name in which the SourceObjectName is located, which is the object the field mapped onto the current entity field belongs to or the target stored procedure belongs to. Used in loops which affect the currentEntityField element or which affect currentSPCall element (SqlServer only) |
<[StartEntityAlias]> |
Will be replaced by the alias for the start entity in a relation in a typed list. A typed list always defines an alias for every entity in the typed list, however this alias could be empty (default), thus the empty string. |
<[TargetType]> |
Will be replaced by the type of the target of an entity, for example Table or View. |
<[TemplateName]> |
Will be replaced by the name of the templatebindings the template file was bound by to the used templateID. |
<[Time]> |
Will be replaced by the current date and time using the "F" format specification. |
<[TypeConverterFullName]> |
Will be replaced by the full name of the type converter Type, including namespace. This name can be used to construct statements which create a new instance of the typeConverter. |
<[TypeOfActualParameter]> |
Will be replaced by the DB Provider type of the stored procedure parameter as it is defined in the stored procedure definition of the current stored procedure call. This is the enum value of the native type in the database types enumeration, for example SqlDbTypes. Used inside currentSPParameter affecting loops. |
<[TypeOfField]> |
Will be replaced by the .NET type of the current entity field, or in case of a valuetypedefinition, the name of the valuetype definition. If the type is an array type, array index operator characters are appended, as specified in the template config file in the tags arrayIndexOperatorStartChar and arrayIndexOperatorCloseChar. |
<[TypeOfMappedTargetField]> |
Will be replaced by the .NET type of the current entityfield/typedview field's target field. This is used to convert back to the original type from a converted value. |
<[TypeOfParameter]> |
Will be replaced by the .NET type of the current stored procedure parameter. If the type is an array type, array index operator characters are appended, as specified in the template config file in the tags arrayIndexOperatorStartChar and arrayIndexOperatorCloseChar. Used in currentSPParameter affecting loops. |
<[TypeOfTypedListField]> |
Will be replaced by the .NET type of the current typed list field. If the type is an array type, array index operator characters are appended, as specified in the template config file in the tags arrayIndexOperatorStartChar and arrayIndexOperatorCloseChar. Used in currentTypedListField affecting loops. |
<[TypeOfTypedViewField]> |
Will be replaced by the .NET type of the current typed view field. If the type is an array type, array index operator characters are appended, as specified in the template config file in the tags arrayIndexOperatorStartChar and arrayIndexOperatorCloseChar. Used in currentTypedViewField affecting loops. |
<[UniqueConstraintIndex]> |
Will be replaced by the index of the current unique constraint in the total list of unique constraints in the current entity. Used in currentEntity affecting loops and uniqueConstraint loops |
<[UserCodeRegionName]> |
Will be replaced by the name of the region, as defined in the last seen UserCodeRegion start statement. |
Name single token statements
Token | Description |
---|---|
<[CurrentEntityName]> |
Will be replaced by the name of the current entity. |
<[CurrentParameterName]> |
Will be replaced by the name of the current parameter in the current stored procedure call. This name is the name of the parameter as specified in the stored procedure call, not in the stored procedure definition itself, which is the actual parameter name. |
<[CurrentSPCallName]> |
Will be replaced by the name of the current stored procedure call. |
<[CurrentTypedListName]> |
Will be replaced by the name of the current typed list |
<[CurrentTypedViewName]> |
Will be replaced by the name of the current typed view. |
<[CurrentValueTypeName]> |
Will be replaced by the name of the current value type definition. |
<[EntityFieldEntityName]> |
Will be replaced by the name of the entity which holds the current entity field. |
<[EntityFieldName]> |
Will be replaced by the name of the current entity field. |
<[IntermediateEntityName]> |
Will be replaced by the name of the intermediate entity of the current entity relation when the relation is an m:n relation. |
<[MappedFieldNameRelatedField]> |
Will be replaced by the name of the field mapped onto a related field. |
<[MappedFieldNameRelation]> |
Will be replaced by the name of the field mapped on the current entity relation. Will be an empty string if the field mapped on the current entity relation is marked hidden or if the current entity relation is hidden. |
<[RelatedEntityFieldName]> |
Will be replaced by the name of the field a field mapped onto a related field is mapped on. |
<[RelatedEntityName]> |
Will be replaced by the name of the entity related to the current entity by the current entity relation. |
<[RelatedEntityPrimaryKeyFieldName]> |
Will be replaced by the name of the current related entity field. |
<[RelatedEntityRelationFieldName]> |
Will be replaced by the name of the field of the entity at the endpoint of the current entity field relation. |
<[RelatedMappedFieldNameRelation]> |
Will be replaced by the name of the related entity's field mapped on the current entity relation. Only used for m:n relations. |
<[RelationFieldName]> |
Will be replaced by the name of the field of the entity at the start point of the current entity field relation. |
<[RelationEndPointName]> |
Will be replaced by the name of the entity which forms the endpoint of the current entity relation |
<[RelationStartPointName]> |
Will be replaced by the name of the entity which forms the startpoint of the current entity relation |
<[ResultsetNumber]> |
Will be replaced by the 1-based index the resultset the current typed view is mapped on has in its owning stored procedure's list of resultsets. |
<[RootEntityName]> |
Will be replaced by the name of the entity which is the root of the hierarchy the currententity is part of. |
<[SuperTypeName]> |
Will be replaced by the name of the supertype of the current entity. |
<[TypedListFieldEntityName]> |
Will be replaced by the name of the entity in which the entity field the current typed list field is mapped on is located. |
<[TypedListFieldName]> |
Will be replaced by the name of the current typed list field. |
<[TypedViewFieldName]> |
Will be replaced by the name of the current typed view field. |
Miscellaneous statements
Token | Description |
---|---|
<[AmountOfElements type]> |
This statement returns the number of elements of the type specified. type can be: Entity, TypedView, TypedList, ActionStoredProcedureCall, RetrievalStoredProcedureCall. |
<[CaseCamel NameSingleTokenStatement]> |
Will be replaced by the value of NameSingleTokenStatement, but then camel cased: the first character is made lowercase. |
<[CallByFKReference SupportNullableTypes]> |
A simple token for a complex piece of code. This token is valid inside a Foreach RelatedEntity OneToMany loop. Where this token is placed, the generator will check in which order the relations of the related entity are emitted in the GetMulti() routine (thus the GetMulti for the ManyToOne relations) and will emit the null keyword where a related entity reference is emitted that is not equal to the current entity. If the relation is with the current entity, it will emit the thisKeyword value as defined in the template set config file. This way, calls to GetMulti() methods can be generated where the current entity is used as a filter. CallByFKReference will check the relation type so it will work with the correct relation. Everything is separated by commas. Inherited relations are also taken into account. The optional parameter SupportNullableTypes which is specified in .NET 2.0 templates for Selfservicing, and which signals the interpreter to append .GetValueOrDefault() calls to the property reference IF the current field is a nullable field AND of a value type. SelfServicing specific. |
<[CallByPKReference]> |
As CallByFKReference, but this token works with PK fields passed to the constructor method of a related entity. The generator will determine the order of the PK fields in the constructor of the related entity and will then, knowing that order, emit thisKeyword.Fieldname for each PK field which is found as a FK in the current entity. (Ex.: 'this.CustomerID' in Order will be emitted in the GetSingleCustomer routine in the entity Order, because it has a ManyToOne relation with Customer, and the PK of Customer is 'CustomerID' which is referred by 'CustomerID', a field in Order.) Everything is separated by commas. SelfServicing specific. |
<[CallByUCReference SupportNullableTypes]> |
As CallByPKReference, but this token works with UC fields passed to the FetchUsingUC... method of a related entity. The generator will |
determine the order of the UC fields in the FetchUsingUC... method of the related entity and will then, knowing that order, emit thisKeyword.Fieldname for each UC field which is found as a FK in the current entity. (Ex.: 'this.CustomerID' in Order will be emitted in the GetSingleCustomer routine in the entity Order, because it has a ManyToOne relation with Customer, and the PK of Customer is 'CustomerID' which is referred by 'CustomerID', a field in Order). The generator also finds out which FetchUsingUC... method to call. The optional parameter SupportNullableTypes which is specified in .NET 2.0 templates for Selfservicing, and which signals the interpreter to append .GetValueOrDefault() calls to the property reference IF the current field is a nullable field AND of a value type. SelfServicing specific.
<[SettingValue ElementType SettingName]>
|This statement directly emits into the output the value for the setting name with the name SettingName for the element with the type
ElementType specified currently in scope. For elementType see <[If SettingValueEquals.. ]>
User code region statements
<[UserCodeRegion "name"]>
* comment *
<[EndUserCodeRegion]>
Defines a user code region in a template with the name specified. If the file which is being constructed already exists and contains a region with the same name, that region with
its contents is placed at the spot of the UserCodeRegion
EndUserCodeRegion
statement combination. If the region doesn't exist, the comment is placed at the spot of the UserCodeRegion
EndUserCodeRegion
statement combination.
<[UserCodeRegion StringValueName Pattern]>
*comment*
<[EndUserCodeRegion]>
As UserCodeRegion "name" but now the name of the region is determined from the StringValueName. StringValueName can be one of the following:
- ActualParameterName
- ActualStoredProcedureName
- ConnectionStringKeyName
- CurrentEntityName
- CurrentParameterName
- CurrentSPCallName
- CurrentTypedListName
- CurrentTypedViewName
- EntityFieldEntityName
- EntityFieldName
- IdentityValueSequenceName
- IntermediateEntityName
- MappedFieldNameRelation
- RelatedEntityName
- RelatedEntityPrimaryKeyFieldName
- RelatedEntityRelationFieldName
- RelatedMappedFieldNameRelation
- RelationEndPointName
- RelationFieldName
- RelationStartPointName
- RootNamespace
- SourceCatalogName
- SourceColumnName
- SourceObjectName
- SourceSchemaName
- TemplateName
- TypedListFieldEntityName
- TypedListFieldName
- TypedViewFieldName
"pattern" is the name pattern to use for the region. The string can be a solid name, or can be a string which can have a macro: ($VALUE)
. The macro ($VALUE)
is replaced with the name value specified using the argument. When using this variant of
UserCodeRegion, use UserCodeRegionName in the marker section for proper name emitting.
Loop statements
Loop statements can all have the optional parameter Separator. Separator can be one of the following:
-
CrLf
, which will cause a\r\n
to be emitted at the end of every loop iteration -
Comma
, which will cause a,
character to be emitted at the end of every loop iteration -
CommaCrLf
, which will cause a comma and a CrLf to be emitted at the end of every loop iteration.
This Separator is defined in the tokens descriptions below as Separator and is always optional
Some loop statements can have a relation specifier RelationType. RelationType can be one of the following:
ManyToMany
, a m:n relationship. Not in Foreach RelationField loopsManyToOne
, a m:1 relationshipOneToMany
, a 1:m relationshipOneToOne
, a 1:1 relationship. Not in Foreach RelationField loops
<[Foreach ActionStoredProcedureCall Separator]>
text
<[NextForeach]>
Will iterate through all the defined Action stored procedure calls and for each action stored procedure call found text is handled further. The loop sorts the action procedure calls ascending before running the loop.
<[Foreach AdditionalInterface Separator]>
text
<[NextForeach]>
Will iterate over the additional interfaces defined in the designer for the entity at hand.
<[Foreach AdditionalNamespace Separator]>
text
<[NextForeach]>
Will iterate over the additional namespaces defined in the designer for the entity at hand.
<[Foreach Attribute ElementType Separator]>
text
<[NextForeach]>
Will iterate through all the additional attributes specified for the element type, identified by ElementType, in scope.
ElementType can be:
- Entity
- ValueType
- Field
- RelatedEntityField (for Fields mapped onto related fields)
- MappedFieldNameRelation (for navigators)
- TypedList
- TypedListField
- TypedView
- TypedViewField
For each additional attribute definition found, text is handled further. Use <[Attribute]> to emit the attribute definition into the output.
<[Foreach CustomProperty Argument Separator]>
text
<[NextForeach]>
Will iterate through all the custom properties (name-value pairs) of the object identified by Argument.
Argument can be:
- Project
- Entity
- ValueType
- Field
- TypedList
- TypedListField
- TypedView
- TypedViewField
- StoredProcedureCall
- MappedFieldNameRelation (for navigators)
- RelatedEntityField (for fields mapped onto related fields)
For each CustomProperty found, text is handled further. Each iteration will set currentCustomProperty global which is used by CustomPropertyName and CustomPropertyValue statements.
<[Foreach Entity Separator]>
text
<[NextForeach]>
Will iterate through each entity found in the executing generator and for each entity found text is handled further The loop sorts the entities ascending before running the loop.
<[Foreach EntityField IncludeInherited|IncludeInheritedPk Separator]>
text
<[NextForeach]>
Will iterate through all the fields mapped on table fields found in the current entity, or if the scope is a value type, the current value type definition. For each field found, text is handled further. If IncludeInherited is specified, all inherited fields including the actual entity fields are iterated. If IncludeInheritedPk is specified, the inherited primary key fields are included in the loop (otherwise they're not, if the current entity is a subtype). Only one argument (IncludeInherited or IncludeInheritedPk) can be specified. Fields are sorted ascending before the loop starts.
<[Foreach EntityRelation Separator]>
text
<[NextForeach]>
Will iterate through all the non-hidden relations of the current typed list. For each relation found, text is handled further.
<[Foreach InputParameter Separator]>
text
<[NextForeach]>
Will iterate through all the input parameters of the current stored procedure call. For each input parameter found, text will be handled further
<[Foreach OutputParameter CursorsOnly|NoCursors Separator]>
text
<[NextForeach]>
Will iterate through all the output parameters of the current stored procedure call. If CursorsOnly is specified, only REF CURSOR or other Cursor typed output parameters are taken into account. If NoCursors is specified, all output parameters are taken into account except REF CURSOR or other Cursor typed output parameters. For each output parameter taken into account, text is handled further
<[Foreach Parameter NoCursors Separator]>
text
<[NextForeach]>
Will iterate through all the parameters of the current stored procedure call. If NoCursors is specified, all parameters are taken into account except REF CURSOR or other Cursor typed parameters. For each parameter taken into account, text is handled further
<[Foreach PrimaryKeyEntityField Separator]>
text
<[NextForeach]>
Will iterate through all the entity fields mapped on table fields which are part of the primary key of the table they're in. For each field found, text is handled further.
<[Foreach RelatedEntity RelationType IncludeInherited Separator]>
text
<[NextForeach]>
Will iterate through all the related entities of the current entity, which are related to the current entity by a non-hidden relation of the type RelationType. For each entity found, text is handled further If IncludeInherited is specified, the complete hierarchy from current entity till the root entity is examined. IncludeInherited has to be specified after the relation type.
<[Foreach RelationField RelationType Separator]>
text
<[NextForeach]>
Will iterate through all the fields in the current entity relation. If a RelationType is specified, it can be ManyToOne or OneToMany. If specified, the current relation has to be an m:n relation, and the ManyToOne argument will make the loop walk all relation fields in the second relation (intermediate entity relation end entity). The OneToMany argument will make the loop walk all relation fields in the first relation (relation start entity intermediate entity).
<[Foreach RelationFieldIsInFkSide Separator]>
text
<[NextForeach]>
Will iterate through all the relations in the current entity, which have the current entity at the FK side and which have the current entity field as a startfield. Ignores 1:n and m:n relations.
<[Foreach RetrievalStoredProcedureCall Separator]>
text
<[NextForeach]>
Will iterate through all the defined retrieval stored procedure calls and for each retrieval stored procedure call found text is handled further. The loop sorts the retrieval procedure calls ascending before running the loop.
<[Foreach SubType Separator]>
text
<[NextForeach]>
Will iterate through all the direct subtypes of the current entity. For each direct subtype found, text is handled further.
<[Foreach TypedList Separator]>
text
<[NextForeach]>
Will iterate through all the typed lists found in the executing generator. For each typed list found, text is handled further. The loop sorts the typed lists ascending before running the loop.
<[Foreach TypedListField Separator]>
text
<[NextForeach]>
Will iterate through all the fields in the current typed list. For each field found, text will be handled further
<[Foreach TypedView MappedOnResultset Separator]>
text
<[NextForeach]>
Will iterate through all the typed views in the executing generator. For each typed view found, text is handled further. The loop sorts the typed views ascending before running the loop. If MappedOnResultset is specified, only typed views which are mapped onto a stored procedure resultset are taken into account. This also brings the stored procedure owning the resultset into scope.
<[Foreach TypedViewField Separator]>
text
<[NextForeach]>
Will iterate through all the fields in the current typed view. For each field found, text will be handled further
<[Foreach UniqueConstraint Separator]>
text
<[NextForeach]>
Will iterate through all the unique constraints found in the current entity, or if the current scope is a valuetype, the current value type definition. For each unique constraint found, text will be handled further
<[Foreach UniqueConstraintEntityField Separator]>
text
<[NextForeach]>
Will iterate through all the fields in the current unique constraint. For each field found, text will be handled further
<[Foreach ValueType Separator]>
text
<[NextForeach]>
Will iterate through all the value type definitions found in the executing generator. For each value type definition found, text will be handled further
If statements
If
statements can sometimes also have a RelationType. See for details
about RelationType, Loop statements above. When Not is specified, the
If statement will be true when the expression is not true, obviously, so
for example <[If Not HasPrimaryKey]>
will be true if the current entity
does not have a field which is a primary key field. Not is always optional.
If
statements also can have an optional Else
token, which defines a block which
is handled further if the If
statement itself isn't resolved to true.
Example:
<[If HasPrimaryKey]>
// some code
<[Else]>
// other code
<[EndIf]>
Statements
<[If ConvertNulledReferenceTypesToDefaultValue]>
text
<[EndIf]>
Will handle text further if the project's property ConvertNulledReferenceTypesToDefaultValue, is set to true..
<[If EntityFieldContainedInCurrentEntity]>
text
<[EndIf]>
Will handle text further if the currentEntityField is contained in the current entity
<[If EntityIsAliassed]>
text
<[EndIf]>
Will handle text further if the currentTypedListField is mapped onto a field in an entity which is aliased
<[If GenerateAsNullableType]>
text
<[EndIf]>
Will handle text further if the current entity field / field mapped on related field, should be generated as a Nullable(Of T) typed field. This is true if the field is nullable AND the field is a value type AND the field's property GenerateAsNullableOfT is set to true. Use in .NET 2.0. Not used for stored procedure parameters, these are always generated as nullable types, if applicable (valuetype)
<[If HasCustomProperty EntityField | Entity | EntityFields]>
text
<[EndIf]>
Will handle text further if the current element with the type specified has one or more custom property definitions (name-value pairs). ]>. If Entity is specified, it resolves to true if the current entity has 1 or more custom properties at the entity level. If the EntityFields is specified, it checks if the current entity has 1 or more entity fields with a custom property defined at the field level. If EntityField is specified, it will resolve to true if the current entity field has 1 or more custom properties defined. If no argument is specified, it will resolve to true if it either has a custom property at the entity level or a custom property at a field level.
<[If HasEntity]>
text
<[EndIf]>
Will handle text further if the executing generator has at least 1 Entity
<[If HasEntityField QuotedString IncludeInherited ]>
text
<[EndIf]>
Will handle text further if the current entity has a field with the name specified as a quoted string. Case sensitive.
<[If HasFields]>
text
<[EndIf]>
Will handle text further if the current entity/typedlist/typedview has any fields mapped.
<[If HasForeignKeyField]>
text
<[EndIf]>
Will handle text further if the current entity has at least 1 foreign key field.
<[If HasForf]>
text
<[EndIf]>
Will handle text further if the current entity has at least 1 field-mapped-onto-related-field definition on the current entity-relationship.
<[If HasInputAndOutputParameters]>
text
<[EndIf]>
Will handle text further if the current stored procedure call has at least 1 input and 1 output parameter.
<[If HasMappedFieldRelation Inherited]>
text
<[EndIf]>
Will handle text further if the current entity has at least 1 navigator mapped onto a relationship. Empty navigators are considered not existing so are skipped. If the optional parameter IncludeInherited is specified also the navigators inherited from the supertype(s) are taken into account: if 1 or more navigators are inherited this statement resolves to true.
<[If HasMultipleCatalogs]>
text
<[EndIf]>
A convenience method to keep code backwards compatible. Selfservicing only. It is used to avoid the catalog name in the field factories and proc methods if there is just one catalog present in the project. Because that was the case in previous versions, users can then decide which database to target with the generated code by using a different connection string. Having the catalog name hardcoded in the code all of a sudden would break these applications.
<[If HasParameter NoCursors | InputParameter ]>
text
<[EndIf]>
Will handle text further if the current stored procedure call has at least 1 input or 1 output parameter. When NoCursors is specified, REF CURSOR parameters or other Cursor typed parameters are ignored. When InputParameter is specified, output parameters are ignored in the expression evaluation.
<[If HasPrimaryKey ]>
text
<[EndIf]>
Will handle text further if the current entity has at least 1 primary key field.
<[If HasRelation RelationType]>
text
<[EndIf]>
Will handle text further if the current entity has at least 1 non-hidden relation of the type RelationType which also doesn't have its field mapped onto the relation marked as hidden.
<[If HasTypeConverterDefined]>
text
<[EndIf]>
Will handle text further if the current entityfield/typedview field/typedlist field (through the mapped entity field) has a type converter defined
<[If HasTypedView]>
text
<[EndIf]>
Will handle text further if the executing generator has at least 1 Typed View
<[If HasTypedList]>
text
<[EndIf]>
Will handle text further if the executing generator has at least 1 Typed List
<[If HasValueType]>
text
<[EndIf]>
Will handle text further if the executing generator has at least 1 value type definition
<[If IsAbstract]>
text
<[EndIf]>
Will handle text further if the current entity is marked abstract.
<[If IsForeignKey]>
text
<[EndIf]>
Will handle text further if the current field is a foreign key.
<[If IsInHierarchyType hierarchyType]>
text
<[EndIf]>
Will handle text further if the current entity is in a hierarchy of the type specified. hierarchyType can be either TargetPerEntityHierarchy, TargetPerEntity or None.
<[If IsMappedOnResultset]>
text
<[EndIf]>
Will handle text further further if the current TypedView in scope is mapped onto a resultset of a stored procedure.
<[If IsNullable]>
text
<[EndIf]>
Will handle text further further if the current entity field / field mapped on related field is nullable in the DB (i.e.: the target field is nullable), OR if the current stored procedure parameter is marked nullable.
<[If IsOneToOnePkPk FkSide]>
text
<[EndIf]>
Will handle text further if the current entity relation is a 1:1 relation and the 1:1 relation is formed by solely PK fields. This can then be used to use different approaches to fetch the related entity: if this expression is true, a PK fetch can be used, otherwise it's an FK-UC 1:1 relation, which means the related entity has to be fetched using a Unique constraint. If FkSide (which is optional) is specified as argument, it will handle text if the relation start fields are the FK side of the PK-PK 1:1 relation.
<[If IsOneToOnePkFkUc FkSide]>
text
<[EndIf]>
Will handle text further if the current entity relation is a 1:1 relation and the 1:1 relation is formed by PK fields on one side and a FK-UC combination on the other side. If FkSide (which is optional) is specified as argument, it will handle text if the relation start fields are the FK side of the PK-FK/UC 1:1 relation.
<[If IsOnPkSide]>
text
<[EndIf]>
Will handle text further if the current entity is on the PK side of the current entity relation. To simplify 1:1 relation usage in templates. It assumes the current entity is the startentity of the current entity relation.
<[If IsPrimaryKey]>
text
<[EndIf]>
Will handle text further if the current entity field is part of the primary key.
<[If IsReadOnly]>
text
<[EndIf]>
Will handle text further if the currentFieldOnRelatedField is readonly or currentEntityField is readonly. Or if not is specified the opposite. Will first evaluate currentFieldOnRelatedField, if that's null, it will evaluate currentEntityField.
<[If IsStringField]>
text
<[EndIf]>
Will handle text further if the current entity field / typed view field / typed list field has as .NET type System.String.
<[If IsSubType]>
text
<[EndIf]>
Will handle text further if the currentEntity is a subtype in an inheritance hierarchy
<[If IsSuperType]>
text
<[EndIf]>
Will handle text further if the currentEntity is a supertype in an inheritance hierarchy. A supertype must have at least one subtype.
<[If IsUpdateOnlyEntity]>
text
<[EndIf]>
Will handle text further if the currentEntity is an update only entity, which is an entity which is mapped onto the same target as the entity it is 'split off', and with which it has a 1:1 pk-pk relationship.
<[If IsValueType]>
text
<[EndIf]>
Will handle text further further if the current entity field / field mapped on related field or stored procedure parameter's type is a value type.
<[If IsValueTypeDefinition]>
text
<[EndIf]>
Will handle text further further if the current entity field has as type a value type definition.
<[If MappedFieldRelationIsHidden]>
text
<[EndIf]>
Will handle text further if the field mapped on the current entity relation is hidden.
<[If OppositeRelationPresent]>
text
<[EndIf]>
Will handle text further if the navigator mapped onto the relationship is empty (i.e. 'hidden')
<[If SettingValueEquals ElementType SettingName QuotedString]>
text
<[EndIf]>
Will handle text further if the value of the setting with name SettingName (a quoted string) is equal to the value specified as QuotedString for the element with type ElementType currently in scope. Spaces are stripped off. The comparison is done case insenstitive. For boolean values, specify "true"/"false"
ElementType can be:
- Entity
- ValueType
- Field
- RelatedEntityField (for Fields mapped onto related fields)
- MappedFieldNameRelation (for navigators)
- TypedList
- TypedListField
- TypedView
- TypedViewField
<[If StringValueEquals StringValueName QuotedString]>
text
<[EndIf]>
Will handle text further if the value of the object with the name specified as StringValueName is equal to the string specified in quotes.
Example: <[If StringValueEquals CurrentEntityName "Order"]>
will return true if the name property of the object referenced by _currentEntity
is equal to "Order".
You can also specify multiple names, delimited by a comma, for example "Order, Product". Spaces are stripped off. The comparison is done case insenstitive.
StringValueName can be one of the following:
- ActualParameterName
- ActualStoredProcedureName
- ConnectionStringKeyName
- CurrentAdditionalInterface
- CurrentEntityName
- CurrentParameterName
- CurrentSPCallName
- CurrentTypedListName
- CurrentTypedViewName
- CurrentValueTypeName
- CustomPropertyName
- CustomPropertyValue
- EntityFieldEntityName
- EntityFieldName
- IdentityValueSequenceName
- IntermediateEntityName
- MappedFieldNameRelation
- RelatedEntityName
- RelatedEntityPrimaryKeyFieldName
- RelatedEntityRelationFieldName
- RelatedMappedFieldNameRelation
- RelationEndPointName
- RelationFieldName
- RelationStartPointName
- RootNamespace
- SourceCatalogName
- SourceColumnName
- SourceObjectName
- SourceSchemaName
- TemplateName
- TemplateGroup
- TypedListFieldEntityName
- TypedListFieldName
- TypedViewFieldName
- TypeOfField
<[If RelatedEntityIsInHierarchyType hierarchyType]>
text
<[EndIf]>
Will handle text further if the current related entity is in a hierarchy of the type specified. hierarchyType can be either TargetPerEntityHierarchy, TargetPerEntity or None.
<[If RelatedEntityIsOtherEntity]>
text
<[EndIf]>
Will handle text further if the related entity (the relation end point) of the current entity relation is another entity than the relation start point (in other words, the current relation is not a relation of the current entity with itself.)
<[If RelationIsInherited]>
text
<[EndIf]>
Will handle text further if the current entity relation is inherited by the current entity.
<[If RelationType RelationType]>
text
<[EndIf]>
Will handle text further if the current entity relation is of the type RelationType.
<[If UsePartialClasses]>
text
<[EndIf]>
Will handle text further if the current task using CodeEmitter in the used generator config has the parameter usePartialClasses set to true.