- Home
- LLBLGen Pro
- Custom Templates
Detecting "text" and "image" fields
Is there someway I can perform an if (using TDL) against the sql data type??
SourceColumnDbType is curiously not part of the StringValueEquals command.
I'm generating some models and in the case a model used for lists, i don't want Image or nText columns being included.
Being able to do an IndexOf/Contains style if against the field name would be handy to.
Ok, that isn't really going to work as I want to exclude an entire property definition from the generated source. I guess I'll have to write this one in C#.
What I want to do is, at the template level, as i'm looping through columns skip over columns that are of type ntext/text or image.
so something along the lines of
<[If Not StringValuesEquals SourceColumnDbType "image"]>
/* property definition here */
<[EndIf]>
I'm trying to modify TDLParser. Should I be able to do that? When I try and run the generator it complains that the TDLParser assembly doesn't match the manifest definition.. thingy. The designer appears to reference the TDLParser assembly with the public key token.
How do I get this to work without the snk?
No it doesn't, it loads the task performers specified in the tasks, so if you overwrite the taskperformers dll AND the tdl interpreter (so you have to build all 4) then you're ok.
still, i think it's way easier to simply use an .lpt template (you can include an .lpt inside a tdl template)
Ah ok. Thank Frans. I guess I'll go with a callable lpt, as its easier to manage than customised llbl libraries.
Ok finally got round to this. I'm just turning the whole template into an lpt...
Now I have an instance of FieldElement which I note has a property called FieldType (IFieldType) which doesn't seem to have anything useful such as the source data type.
I want the sql type of the source column.
There used to be a property called "MappedField".
...the object model certainly got a lot more complicated.
This one way I've found (i'm running this inside a template where activeObject is an entity).
Please let me know if theres a more direct way.
(at top top of my template)
<%
string rns = _executingGenerator.ProjectDefinition.Properties.RootNameSpace;
EntityDefinition ed = _activeObject as EntityDefinition;
var edMappings = _executingGenerator.ProjectDefinition.MappingData.GetAllEntitiesWithTheirMappingsForDatabase("2D18D138-1DD2-467E-86CC-4838250611AE")
[ed];
%>
Is that GUID ever going to change??
then later in a for loop of the entity fields where "f" is the FieldElement:
var targetField = edMappings.GetFieldMappingOfField(f).MappedTarget;
string typeName = GetCSharpTypeName(f.FieldType.RepresentedType);
string dbType = targetField.DbTypeAsString;
worldspawn wrote:
Ok finally got round to this. I'm just turning the whole template into an lpt...
Now I have an instance of FieldElement which I note has a property called FieldType (IFieldType) which doesn't seem to have anything useful such as the source data type.
yes it does, it's the 'RepresentedType' property
FieldType is a TypeShortcut or a ValueTypeDefinition. So in your own templates, if you don't use ValueTypes (llblgen pro runtime doesn't support them yet), you can simply ignore the test and always read the RepresentedType property.
I want the sql type of the source column. There used to be a property called "MappedField".
yes, but an entity field can be mapped onto more than 1 target field. So you have to obtain the GroupableModelElementMapping object, which is the mapping of the entity, then ask that one for the fieldmapping, which contains a MappedTarget property which contains the target field.
it's easier if you look into for example the linq to sql templates or nhibernate templates, which are in .lpt and contain the logic you're after.
worldspawn wrote:
...the object model certainly got a lot more complicated.
There's more in there, but the logic to help you is also there.
This one way I've found (i'm running this inside a template where activeObject is an entity). Please let me know if theres a more direct way. (at top top of my template)
<% string rns = _executingGenerator.ProjectDefinition.Properties.RootNameSpace; EntityDefinition ed = _activeObject as EntityDefinition; var edMappings = _executingGenerator.ProjectDefinition.MappingData.GetAllEntitiesWithTheirMappingsForDatabase("2D18D138-1DD2-467E-86CC-4838250611AE") [ed]; %>
Is that GUID ever going to change??
No, but you shouldn't do it that way. Use the _executingGenerator.DriverID property for the driverid guid currently generated. Use the RootNamespaceToUse property on the _executingGenerator to obtain the root namespace, this in case you're generating a project per group for example.
To obtain the mapping for an entity, use: var edMapping = _executingGenerator.ProjectDefinition.GetGroupableModelElementMapping(ed, _executingGenerator.DriverID);
then later in a for loop of the entity fields where "f" is the FieldElement:
var targetField = edMappings.GetFieldMappingOfField(f).MappedTarget; string typeName = GetCSharpTypeName(f.FieldType.RepresentedType); string dbType = targetField.DbTypeAsString;
That's pretty much it. Also take a look at the GeneratorUtils class in Generatorcore which has some helper methods which might make things easier.
Thanks for explaining that Frans.
I have one other query in my re-discovery of llbl extending. I've just made a plugin that attaches an interface called IUser to any entity called "User". And if the entity has 4 properties called "UpdatedOn", "UpdatedBy", "CreatedOn", "CreatedBy" it adds IUpdateable which just an interface I test for in my domain service to automate the setting of those 4 properties.
Typically I implement IUser with this method:
// __LLBLGENPRO_USER_CODE_REGION_START CustomEntityCode
public IList<Shivam.ASL.Core.Model.IRole> Roles
{
get
{
return this.RoleCollectionViaUserRole.Cast<Shivam.ASL.Core.Model.IRole>().ToList();
}
set
{
throw new NotImplementedException();
}
}
// __LLBLGENPRO_USER_CODE_REGION_END
I have all this abstracted security that relies on this. I was wondering if there was some way to leverage plugins to insert this bit of into this region... I know theres nothing like that via the designer so the answers probably no. But I wanted to avoid editing any of the llbl templates. Any suggestions?
Edit: I modified the preset (not the templates) and create a new template with a partial class of the entity that implemented what needed implementing.
Oh and for sharings sake, heres my 'models' template I use with mvc apps. It does assign a few custom attributes though but they can be swapped for native data annotations or removed completely.
<[ System.Text.RegularExpressions ]><%
string rns = _executingGenerator.RootNamespaceToUse;
EntityDefinition ed = _activeObject as EntityDefinition;
var edMappings = _executingGenerator.ProjectDefinition.GetGroupableModelElementMapping(ed, _executingGenerator.DriverID);
var rels = _executingGenerator.ProjectDefinition.GetAllRelationshipsForEntity(ed, true);
%><~
string GetCSharpTypeName(Type type)
{
string name = type.FullName;
switch (name)
{
case "System.String" :
return "string";
case "System.Int16" :
return "short";
case "System.Int32" :
return "int";
case "System.Int64" :
return "long";
case "System.Decimal" :
return "decimal";
case "System.Single" :
return "float";
case "System.Double" :
return "double";
case "System.SByte" :
return "sbyte";
case "System.Byte" :
return "byte";
case "System.Boolean" :
return "bool";
}
return name;
}
bool IsPartOfUpdateable(FieldElement field)
{
var checkFor = new [] {"UpdatedBy", "UpdatedOn", "CreatedBy", "CreatedOn" };
return checkFor.Contains(field.Name);
}
public class ModelFieldAttribute
{
public ModelFieldAttribute(){ ConstructorArguments = new List<string>(); }
public string Name{ get; set; }
public List<string> ConstructorArguments { get;set; }
}
public class AttributeSet : List<ModelFieldAttribute>
{
public string Render()
{
List<string> bits = new List<string>();
foreach (var attr in this)
{
string attribute = attr.Name;
if (attr.ConstructorArguments.Count > 0)
attribute += "(" + string.Join(", ", attr.ConstructorArguments.ToArray()) + ")";
bits.Add(attribute);
}
if (bits.Count() == 0)
return null;
return string.Format("[{0}]{1}\t", string.Join(", ", bits.ToArray()), Environment.NewLine);
}
}
string CreateFriendlyName(string name){
Regex acronym = new Regex("^[A-Z0-9]+(Id)?$");
Regex exp = new Regex("(\\w)([A-Z])"),
idExp = new Regex("(\\w)Id$");
if (idExp.IsMatch(name))
{
if (acronym.IsMatch(name))
return idExp.Replace(name, "$1");
return exp.Replace(idExp.Replace(name, "$1"), "$1 $2");
}
if (acronym.IsMatch(name))
return name;
return exp.Replace(name, "$1 $2");
}
~>
using System.Web.Mvc;
using Shivam.ASL.Core.Model.Validators;
using Shivam.ASL.Core.Model;
using System.ComponentModel.DataAnnotations;
namespace <%= rns %>.Web.Models
{
#region Add Model
<% foreach (var f in ed.Fields){
if (IsPartOfUpdateable(f))
continue;
if (f.IsPartOfIdentifyingFields)
continue;
var targetField = edMappings.GetFieldMappingOfField(f).MappedTarget;
string typeName = GetCSharpTypeName(f.FieldType.RepresentedType);
string dbType = targetField.DbTypeAsString;
AttributeSet aset = new AttributeSet();
if (!f.IsOptional && typeName != "bool")
aset.Add(new ModelFieldAttribute() {Name="RequiredField"});
if (f.IsForeignKeyField)
aset.Add(new ModelFieldAttribute() {Name="UIHint", ConstructorArguments = {@"""SelectList"""}});
if (dbType == "ntext")
aset.Add(new ModelFieldAttribute() {Name="CKEditor"});
else{
if (typeName == "string"){
aset.Add(new ModelFieldAttribute() {Name="Length", ConstructorArguments = {f.MaxLength.ToString()}});
if (f.MaxLength >= 256)
aset.Add(new ModelFieldAttribute() {Name="DataType", ConstructorArguments = {"DataType.MultilineText"}});
}
}
if (typeName == "System.DateTime")
aset.Add(new ModelFieldAttribute() {Name="DataType", ConstructorArguments = {"DataType.Date"}});
if (typeName != "string" && f.IsOptional)
typeName += "?";
string fieldName = f.Name;
string friendlyName = CreateFriendlyName(fieldName);
if (fieldName != friendlyName)
aset.Add(new ModelFieldAttribute() {Name="DisplayName", ConstructorArguments = {@"""" + friendlyName + @""""}});
%>
<%= aset.Render()%>public <%= typeName %> <%= f.Name %>
{
get;
set;
}
<% }
foreach(var rel in rels){
if (!(rel.RelationshipType == EntityRelationshipType.ManyToMany))
continue;
var mmRel = rel as IndirectRelationshipEdge;
AttributeSet aset = new AttributeSet();
aset.Add(new ModelFieldAttribute() {Name="DisplayName", ConstructorArguments = {@"""" + CreateFriendlyName(mmRel.SecondRelationship.EntityPkSide.Name + "s") + @""""}});
%>
<%= aset.Render()%>public int[] <%= rel.StartEntityNavigator %>
{
get;
set;
}
<%
}
%>
#endregion
#region Edit Model
<% foreach (var f in ed.Fields){
var targetField = edMappings.GetFieldMappingOfField(f).MappedTarget;
string typeName = GetCSharpTypeName(f.FieldType.RepresentedType);
string dbType = targetField.DbTypeAsString;
AttributeSet aset = new AttributeSet();
if (!f.IsOptional && typeName != "bool" && !IsPartOfUpdateable(f))
aset.Add(new ModelFieldAttribute() {Name="RequiredField"});
if (f.IsPartOfIdentifyingFields){
aset.Add(new ModelFieldAttribute() {Name="HiddenInput", ConstructorArguments = {"DisplayValue = false"}});
}
else{
if (IsPartOfUpdateable(f))
aset.Add(new ModelFieldAttribute() {Name="ReadOnly", ConstructorArguments = {"true"}});
if (f.IsForeignKeyField)
aset.Add(new ModelFieldAttribute() {Name="UIHint", ConstructorArguments = {@"""SelectList"""}});
if (dbType == "ntext")
aset.Add(new ModelFieldAttribute() {Name="CKEditor"});
else{
if (typeName == "string"){
aset.Add(new ModelFieldAttribute() {Name="Length", ConstructorArguments = {f.MaxLength.ToString()}});
if (f.MaxLength >= 256)
aset.Add(new ModelFieldAttribute() {Name="DataType", ConstructorArguments = {"DataType.MultilineText"}});
}
}
if (typeName == "System.DateTime")
aset.Add(new ModelFieldAttribute() {Name="DataType", ConstructorArguments = {"DataType.Date"}});
if (typeName != "string" && f.IsOptional)
typeName += "?";
}
string fieldName = f.Name;
string friendlyName = CreateFriendlyName(fieldName);
if (fieldName != friendlyName)
aset.Add(new ModelFieldAttribute() {Name="DisplayName", ConstructorArguments = {@"""" + friendlyName + @""""}});
%>
<%= aset.Render()%>public <%= typeName %> <%= f.Name %>
{
get;
set;
}
<% }
foreach(var rel in rels){
if (!(rel.RelationshipType == EntityRelationshipType.ManyToMany))
continue;
var mmRel = rel as IndirectRelationshipEdge;
AttributeSet aset = new AttributeSet();
aset.Add(new ModelFieldAttribute() {Name="DisplayName", ConstructorArguments = {@"""" + CreateFriendlyName(mmRel.SecondRelationship.EntityPkSide.Name + "s") + @""""}});
%>
<%= aset.Render()%>public int[] <%= rel.StartEntityNavigator %>
{
get;
set;
}
<%
}
%>
#endregion
#region List Model
<% foreach (var f in ed.Fields){
var targetField = edMappings.GetFieldMappingOfField(f).MappedTarget;
string typeName = GetCSharpTypeName(f.FieldType.RepresentedType);
string dbType = targetField.DbTypeAsString;
AttributeSet aset = new AttributeSet();
string fieldName = f.Name;
string friendlyName = CreateFriendlyName(fieldName);
if (fieldName != friendlyName)
aset.Add(new ModelFieldAttribute() {Name="DisplayName", ConstructorArguments = {@"""" + friendlyName + @""""}});
if (typeName != "string" && f.IsOptional)
typeName += "?";
%>
<%= aset.Render()%>public <%= typeName %> <%= f.Name %>
{
get;
set;
}
<% }
foreach(var rel in rels){
if (!(rel.RelationshipType == EntityRelationshipType.ManyToMany))
continue;
var mmRel = rel as IndirectRelationshipEdge;
AttributeSet aset = new AttributeSet();
aset.Add(new ModelFieldAttribute() {Name="DisplayName", ConstructorArguments = {@"""" + CreateFriendlyName(mmRel.SecondRelationship.EntityPkSide.Name + "s") + @""""}});
%>
<%= aset.Render()%>public string[] <%= rel.StartEntityNavigator %>
{
get;
set;
}
<%
}
%>
#endregion
}