Detecting "text" and "image" fields

Posts   
 
    
worldspawn avatar
worldspawn
User
Posts: 321
Joined: 26-Aug-2006
# Posted on: 10-Jun-2010 08:25:52   

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.

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 10-Jun-2010 11:26:43   

You may use something like:

if(SqlDbType.<[SourceColumnDbType]> == XYZ)
{

}
worldspawn avatar
worldspawn
User
Posts: 321
Joined: 26-Aug-2006
# Posted on: 11-Jun-2010 02:00:39   

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#.

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 11-Jun-2010 04:30:35   

It is not 100% what you want. Could you please poat an example of the final code snippet you want to generate?

David Elizondo | LLBLGen Support Team
worldspawn avatar
worldspawn
User
Posts: 321
Joined: 26-Aug-2006
# Posted on: 11-Jun-2010 05:58:34   

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]>

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 11-Jun-2010 08:21:34   

Please try an lpt template for this.

worldspawn avatar
worldspawn
User
Posts: 321
Joined: 26-Aug-2006
# Posted on: 11-Jun-2010 18:36:37   

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?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 11-Jun-2010 19:24:58   

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)

Frans Bouma | Lead developer LLBLGen Pro
worldspawn avatar
worldspawn
User
Posts: 321
Joined: 26-Aug-2006
# Posted on: 16-Jun-2010 06:16:55   

Ah ok. Thank Frans. I guess I'll go with a callable lpt, as its easier to manage than customised llbl libraries.

worldspawn avatar
worldspawn
User
Posts: 321
Joined: 26-Aug-2006
# Posted on: 15-Jul-2010 06:55:42   

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".

worldspawn avatar
worldspawn
User
Posts: 321
Joined: 26-Aug-2006
# Posted on: 15-Jul-2010 08:29:42   

...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;

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 15-Jul-2010 12:00:26   

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 simple_smile

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.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 15-Jul-2010 12:06:21   

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. simple_smile

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.

Frans Bouma | Lead developer LLBLGen Pro
worldspawn avatar
worldspawn
User
Posts: 321
Joined: 26-Aug-2006
# Posted on: 15-Jul-2010 12:28:15   

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.

worldspawn avatar
worldspawn
User
Posts: 321
Joined: 26-Aug-2006
# Posted on: 15-Jul-2010 12:35:45   

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
}