Finding an entity's relations in LPT template

Posts   
 
    
ww
User
Posts: 83
Joined: 01-Oct-2004
# Posted on: 13-May-2011 19:16:40   

I'm using LLBLGen v3. I have an LPT template written in C# in which I need to accomplish the following:

  • Find a relation in the current entity, given its navigator name.
  • Generate different code depending on the relation type (OneToMany,ManyToOne, OneToOne).

I can't figure out how to find the relation, given an EntityDefinition.

Please let me know what I'm missing...

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 13-May-2011 19:54:13   

Try this:

// here project is your ProjectDefinition object
var relationships = project.GetAllRelationshipsForEntity(yourEntity, true);
var rel = relationships.Where(r=>r.StartEntityNavigator == "SomeValidatorName");

switch (rel.RelationshipType)
{
     case EntityRelationshipType.OneToOne:
     ...
     break;

     case EntityRelationshipType.OneToMany:
     ...
     break;

     ... etc
}
David Elizondo | LLBLGen Support Team
ww
User
Posts: 83
Joined: 01-Oct-2004
# Posted on: 13-May-2011 21:41:05   

Perfect, thanks. I was looking at properties and methods on the EntityDefinition--I didn't think to look at the project methods.

Posts: 26
Joined: 29-Sep-2011
# Posted on: 14-Mar-2012 23:42:21   

I need to convert the following v2.6 template code to v3 template code.

//automatic relations for (int i = 0; i < currentEntity.Relations.Count; i++) { bool process = false; if (currentEntity.Relations[i].RelationType != EntityRelationType.ManyToMany) { process = currentEntity.Relations[i].StartEntityIsPkSide; }

        if (process) {
            switch (currentEntity.Relations[i].RelationType)
            {
                case EntityRelationType.OneToMany:
                    __outputWriter.Write("      private {0}DTOCollection f{1};\r\n", currentEntity.Relations[i].RelationEndName, currentEntity.Relations[i].RelationEndName);
                    __outputWriter.Write("      public {0}DTOCollection {1} {{ get {{ return f{1}; }} set {{ f{1} = value; }} }}\r\n", currentEntity.Relations[i].RelationEndName, currentEntity.Relations[i].UtilizingPropertyName);
                    break;
                case EntityRelationType.ManyToOne:
                case EntityRelationType.OneToOne:
                    __outputWriter.Write("      private {0}DTO f{1};\r\n", currentEntity.Relations[i].RelationEndName, currentEntity.Relations[i].UtilizingPropertyName);
                    __outputWriter.Write("      public {0}DTO {1} {{ get {{ return f{1}; }} set {{ f{1} = value; }} }}\r\n", currentEntity.Relations[i].RelationEndName, currentEntity.Relations[i].UtilizingPropertyName);
                    break;
            }
        }
    }

and this is what i have so far and i am not sure if this is right

        var relationships = _executingGenerator.ProjectDefinition.GetAllRelationshipsForEntity(currentEntity, true);
        foreach (var rel in relationships)
        {
               bool process = false;
                if (relEdge.RelationshipType != EntityRelationshipType.ManyToMany)
                {
                    if (rel is NormalRelationshipEdge)
                    {
                        NormalRelationshipEdge nEdge = (NormalRelationshipEdge)rel;
                        process = nEdge.StartEntityIsPkSide;
                    }

                }
                if (process)
                {
                    if (rel is NormalRelationshipEdge)
                    {
                        NormalRelationshipEdge nEdge = (NormalRelationshipEdge)rel;
                        switch (nEdge.RelationshipType)
                        {
                            case EntityRelationshipType.OneToMany:
                                __outputWriter.Write("      private {0}DTOCollection f{1};\r\n", relEdge.EndEntityNavigator, relEdge.UniqueAssociationName);
                                __outputWriter.Write("      public {0}DTOCollection {1} {{ get {{ return f{1}; }} set {{ f{1} = value; }} }}\r\n", relEdge.EndEntityNavigator, relEdge.UniqueAssociationName);
                                break;
                            case EntityRelationshipType.ManyToOne:
                            case EntityRelationshipType.OneToOne:
                                __outputWriter.Write("      private {0}DTO f{1};\r\n", relEdge.EndEntityNavigator, relEdge.UniqueAssociationName);
                                __outputWriter.Write("      public {0}DTO {1} {{ get {{ return f{1}; }} set {{ f{1} = value; }} }}\r\n", relEdge.EndEntityNavigator, relEdge.UniqueAssociationName);
                                break;
                        }
                    }
                }
            }

The problem i am having is the StartEntityIsPKSide is always false even if the current entity is the primary key table.

For example I have two table ui_audit_sch_ltrs_hdr and ui_audit_sch_ltrs_dtl and they have one to many relationship between them. But when i call the method GetAllRelationshipsForEntity for the current entity the relations I get is reverse of what I have in the database. So if i have one-to-many relationship the normalrelationship edge RelationType property value is ManyToOne.

I am attaching the quick watch window of the relations object from visual studio. If you see in the attached image the startvertex is uiauditschltrsdtl and endvertext is uiauditschltrshdr and i think it should be the otherway.

Thanks

Sunil Gaddam

Posts: 26
Joined: 29-Sep-2011
# Posted on: 14-Mar-2012 23:58:33   

Forgot to add the attachment - Sorry

Attachments
Filename File size Added on Approval
relationship_vs_debug.gif 163,792 15-Mar-2012 00:01.42 Approved
Walaa avatar
Walaa
Support Team
Posts: 14986
Joined: 21-Aug-2005
# Posted on: 15-Mar-2012 11:38:38   

This was an issue in v.3.0 but should be fixed in v.3.1 Could you please use the latest release of v.3.1

Posts: 26
Joined: 29-Sep-2011
# Posted on: 15-Mar-2012 17:19:05   

I downloaded the latest version v3.1 and i am still having the same issue. I am attaching an image with assembly version info of the core dlls.

Let me know what needs to be done to fix this issue.

Thanks

Sunil Gaddam

Attachments
Filename File size Added on Approval
v3.1_Feb24_assembly_Version.gif 100,255 15-Mar-2012 17:19.53 Approved
daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 15-Mar-2012 21:48:31   

I'm not sure whether or not this is a bug, I suspect that old v3.0 bug is something else. Let me explain from my experience: the edge may have any direction PK<->FK or FK<->PK, that depends on how the relationship was created, normally the relationships that results from reverse-engineer the DB result in m:1 edges where the start entity id FK side and the end entity is the PK side. If you create a new relationship from the designer and you create it from the PK entity, the start entity would be the PK side and the end entity would be the FK side. So the direction is not relevant in your decision on whether or not process de relationship. Your interest is to know whether the entity you are processing is the PK side of the relationship. Try this:

if (rel is NormalRelationshipEdge)
{
     NormalRelationshipEdge nEdge = (NormalRelationshipEdge)rel;
     process = (nr.EntityPkSide.Name == entity.Name);
}

Also take this into account in the rest of your code. You should use relEdge.NavigatorFkSide instead of relEdge.EndEntityNavigator, because it could be that the EndNavigator is the Pk side.

David Elizondo | LLBLGen Support Team
Posts: 26
Joined: 29-Sep-2011
# Posted on: 16-Mar-2012 01:08:50   

In my template code I have a switch statement checking for relation type and if Llblgen always return the reverse of the actual relationship type in the database then I will have to change the code in my template.

How come v2.6 returns the correct relationship type ?

Also relEdge.NavigatorFkSide returns primary key entity name which is wrong it should be the fk entity name.

Thanks

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39760
Joined: 17-Aug-2003
# Posted on: 16-Mar-2012 11:25:12   

I now see you missed an important thing simple_smile In v2.6, for every relationship there were 2 objects. Say you have Customer 1:n Order. In v2.6, there were 2 objects: Customer 1:n Order and Order m:1 Customer. In v3 there's just 1 object. When using reverse engineering to build your model, all relationship objects are always created like fkside relationshiptype pkside, so in the example above: Order m:1 Customer.

This relationship object, Order (startentity) m:1 Customer (endentity), is the 'edge' in a non-directed graph between Customer and Order (from both sides, so Order -> Customer and Customer -> Order). For this relationship object, Order m:1 Customer, StartEntityIsPkSide is false, as Order is the FK side.

There are methods available for you to obtain the information you need (we use them in the entity framework, l2s and nhibernate templates), but I don't know for sure what you want to accomplish. They key is however that you step away from the idea that if you are obtaining the relationships for Order, you'll get a different object for Order m:1 Customer than when you are obtaining the relationships for Customer, in v3 you'll get the same object: Order m:1 Customer.

The best way I think is to start with the GeneratorlUtils methods (a class in the GeneratorCore assembly, see core designer reference manual). It contains a method called GetAllRelationshipInfosForEntity, which will return a list of RelationshipInfo objects which contain information per relationship and a relationshipinfo object's properties are valid for the entity you passed in.

So if we call that method for 'Order', we'll get a RelationshipInfo object back for Order m:1 Customer, where 'Navigator' has the value 'Customer', and 'OppositeNavigator' has the value 'Orders'. If we call the same method for 'Customer', we'll get a RelationshipInfo object back for the same relationship object Order m:1 Customer (as there's just 1!) where 'Navigator' is 'Orders' and 'OppositeNavigator' is 'Customer'. Please have a look at that method and also the EF templates for 'Entity', e.g. the Poco entity template which shows how this method can be used, line 325 and further.

Frans Bouma | Lead developer LLBLGen Pro
Posts: 26
Joined: 29-Sep-2011
# Posted on: 22-Mar-2012 07:11:20   

Thanks Otis for the detailed explanation. Entity framework template code was really helpful for me in upgrading my v2.6 templates.

One more question

How can I find out the sequence name and database field type. In v2.6 I was using IdentityValueSequenceName and MappedFieldDBTypeAsString properties on the entity field definition but in the newer version I didn't find these properties.

Thanks

Sunil Gaddam

Posts: 26
Joined: 29-Sep-2011
# Posted on: 22-Mar-2012 07:42:59   

Otis - Ignore my previous question I found the answer in a different thread.

Thanks

Sunil