How to iterate through entity properties and create entity fields tree?

Posts   
 
    
Posts: 15
Joined: 16-May-2012
# Posted on: 23-Jul-2012 16:28:15   

Hello,

How i could itterae through entity properties and create a entity properties tree object. For example i have entity Person and that entity have relationships with other entities, so i need to generate a tree with all of them.

Person --Name --Address --Zip --LastName --ClsfCountryId |--Id |--CountryName |--CountryCode --UserId |--Id |--UserName |--UserTypeId |--Id |--TypeName

Any kind of help will be highly appreciated!

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 24-Jul-2012 08:01:19   

Hi there,

Could you explain a little more the why you need this? Maybe we can guide you on the right direction based on your needs. For instance, you could use a custom template to use the metadata in your project and generate some code file that feeds some tree structure.

David Elizondo | LLBLGen Support Team
Posts: 15
Joined: 16-May-2012
# Posted on: 24-Jul-2012 08:36:49   

Hello, thank you for the message. Basically I'm creating dynamic reports. There is two parts, report filter configurator and report generator. I need that tree for dynamic report configurator where you can tell for report which fields can be used for dynamic list generation.

So in configurator i need to create entities and properties tree so user could easily select which fields he want to add into dynamic report.

Hope that makes some sense. simple_smile Thanks for the help guys.

daelmo wrote:

Hi there,

Could you explain a little more the why you need this? Maybe we can guide you on the right direction based on your needs. For instance, you could use a custom template to use the metadata in your project and generate some code file that feeds some tree structure.

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 25-Jul-2012 07:13:50   

This is an idea to obtain a 1-level members of a given entityName:

public Dictionary<string, string> GetMembers(string entityName)
{
    var factory = EntityFactoryFactory.GetFactory((EntityType)Enum.Parse(typeof(EntityType), entityName));
    var entity = factory.Create();

    var fieldNames = entity.Fields.Select(f => f.Name);
    var navigators = entity.GetAllRelations().Select(r => r.MappedFieldName);

    var toReturn = new Dictionary<string, string>();
    foreach (var f in fieldNames)
    {
        toReturn.Add(f, "field");
    }

    foreach (var n in navigators)
    {
        toReturn.Add(n, "navigator");
    }

    return toReturn;            
}

You can show that in any .net tree control. Then, if the user click on a node that is a "navigator" you can obtain its type entity name and expand it using the same function, and so on. If you try to build the full from the beginning you may end up with something like customer->order->shipAddress->customer->order->...

David Elizondo | LLBLGen Support Team
Posts: 15
Joined: 16-May-2012
# Posted on: 03-Aug-2012 10:57:40   

hey, thanks a lot for helpful code. I would like to ask you for advice. simple_smile

I create dynamic reports for entities. So report is entity for sample "Person". And i have another table where i store properties which is available for report filter. For sample "ReportProperty"

what kind of information would be best to store in property table if i want to determine field and his relation?

because i'm writing a dynamic data extractor so i store information about fields in database. So i need to create a column/columns for property relation information. So later i could use reflection or llblgen tools to get relations and field information out and pass it into dao.

So what would be the best to put there?

im thinking about

String relation name and later use reflection get that relation item out?

or

Field name and entity name where is that field from? so later i would scan entities relations and get the specific field relation. using that method what you posted in my later post.

what would you do in this situation, maybe you have better ideas simple_smile ?

thank you for all help guys.

daelmo wrote:

This is an idea to obtain a 1-level members of a given entityName:

public Dictionary<string, string> GetMembers(string entityName)
{
    var factory = EntityFactoryFactory.GetFactory((EntityType)Enum.Parse(typeof(EntityType), entityName));
    var entity = factory.Create();

    var fieldNames = entity.Fields.Select(f => f.Name);
    var navigators = entity.GetAllRelations().Select(r => r.MappedFieldName);

    var toReturn = new Dictionary<string, string>();
    foreach (var f in fieldNames)
    {
        toReturn.Add(f, "field");
    }

    foreach (var n in navigators)
    {
        toReturn.Add(n, "navigator");
    }

    return toReturn;            
}

You can show that in any .net tree control. Then, if the user click on a node that is a "navigator" you can obtain its type entity name and expand it using the same function, and so on. If you try to build the full from the beginning you may end up with something like customer->order->shipAddress->customer->order->...

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 04-Aug-2012 01:59:22   

You are welcome wink

About your question, if I have to do something like that, my table would look like

ReportMetadataItem

ReportMetadataItemId (int) FieldName (string) EntityName (string) IsNavigator (bool)

I wouldn't use column/table names because sometimes your Entity/Field names are different. Since you are dealing with LLBLGen objects, it's better to use that names.

Using the relation name would be a little hard I think. If you want to store relation information, you should do it in a way like: PKSideEntityName PKSideFieldName FKSideEntityName FKSideFieldName ... remember that you could have composite PKs, so you should store that as well.

Another idea is to generate that info instead of storing it in your DB. Since your LLBLGen project already have such metadata you could create a template that generate ReportingMetadata classes. If you want to go further, you could create custom attributes on your entity/fields to signal what fields are candidates for reporting, so just them will be generated. That would be more elegant but requires to do template coding.

David Elizondo | LLBLGen Support Team
Posts: 15
Joined: 16-May-2012
# Posted on: 06-Aug-2012 10:23:36   

hey thanks!

i was thinking about similar table structure. thanks a lot.

but for example

if i have entity Person and that entity have a relation from entity User

and i want create a search on field UserName. so i need to join them two tabled through PersonId which is in User and display UserName field content.

so i would add UserName is report property table and User in entity name column. But i think i need one more column to determine a navigator property in User entity "PersonId" which i gonna use to access UserName column from user entity. otherwise i will not be able to find a relationship on that field and will not be able to join them tables. what do you think on this one ? simple_smile thank you

daelmo wrote:

You are welcome wink

About your question, if I have to do something like that, my table would look like

ReportMetadataItem

ReportMetadataItemId (int) FieldName (string) EntityName (string) IsNavigator (bool)

I wouldn't use column/table names because sometimes your Entity/Field names are different. Since you are dealing with LLBLGen objects, it's better to use that names.

Using the relation name would be a little hard I think. If you want to store relation information, you should do it in a way like: PKSideEntityName PKSideFieldName FKSideEntityName FKSideFieldName ... remember that you could have composite PKs, so you should store that as well.

Another idea is to generate that info instead of storing it in your DB. Since your LLBLGen project already have such metadata you could create a template that generate ReportingMetadata classes. If you want to go further, you could create custom attributes on your entity/fields to signal what fields are candidates for reporting, so just them will be generated. That would be more elegant but requires to do template coding.

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 07-Aug-2012 07:56:23   

Yes, you would need the navigator name, but it's known by your tree. For instance, if you are navigating from Person, then the user must click the navigator "User", then select the field "UserName". When the user clicks "User" or the user adds "UserName" you should be able in your GUI to know that UserName comes from the "User" node which is child of PersonEntity node. Example of the tree:

PersonEntity (selected) -- PersonId -- Age -- ... -- User (selected) ----- PersonId ----- UserName (selected) ----- Password ----- ... -- ...

If you are capable to obtain such structure in your GUI, then you should know that the User selected PersonEntity, the navigator PersonEntity-User, and the field PersonEntity-User-UserName. For each navigator selected in the tree you should add the corresponding relation in your filter. The pseudo code should look like:

// add relations based on the tree selection
for every LEAF in TREE do
     if LEAF.PARENT  is NAVIGATOR then
          RELATION_TO_ADD = FindRelation(entityName = LEAF.PARENT.PARENT, navigatorName = LEAF.PARENT)
          AddToRelations(RELATION_TO_ADD)
      end
end

Of course you could store the relation info in your ReportMetadata table, but that would be more complex.

David Elizondo | LLBLGen Support Team