binding to inherited subtypes

Posts   
1  /  2
 
    
tangent
User
Posts: 41
Joined: 30-Apr-2006
# Posted on: 13-Apr-2007 00:01:52   

OK I am probably doing something stupid, but I have searched the forums up and down and have been working on this for way too long..

I have the following inheritance heirarchy:

PersonEntity -- 1:n -- ContactMechanismEntity ContactMechanismEntity is a TargetPerEntity supertype with 3 subtypes, PhoneEntity, AddressEntity, ElectronicAddressEntity

I want to fetch the person entity and prefetch all their related contact information, ie I want to prefetch the super-type and all sub-types

here is my code


        public PersonEntity getPersonData(int PersonID)
        {
            PersonEntity Person; //= new PersonEntity(PersonID);

            using (DataAccessAdapter adapter = new DataAccessAdapter())
            {
                IRelationPredicateBucket bucket = new RelationPredicateBucket((PersonFields.Pid == PersonID));
                IPrefetchPath2 prefetchPath = new PrefetchPath2((int)EntityType.PersonEntity);
                prefetchPath.Add(PersonEntity.PrefetchPathPersonNote);
                prefetchPath.Add(PersonEntity.PrefetchPathPersonFee);

                IPrefetchPathElement2 prefetchContacts =
                    PersonEntity.PrefetchPathContactMechanism;
                prefetchPath.Add(prefetchContacts);

                Person = (PersonEntity)adapter.FetchNewEntity(new PersonEntityFactory(), bucket, prefetchPath);
                //adapter.FetchEntity(Person, prefetchPath);  (this doesn't work either)
            }
            return Person;
        }

everything works, the PersonEntity and all ContactMechanismEntities are fetched but I can't for the life of me figure out how to get to the subtypes.. ie Person.ContactMechanism is a collection of ContactMechanismEntities but there is no Person.ContactMechanism.Phone

i looked at the query being executed and i can see the subtypes are being fetched.. i just can't figure out how to access them!

         Generated Sql query: 
Query: SELECT DISTINCT [pgDB].[dbo].[contact_mechanism].[contact_mechanism_id] AS [F0], [pgDB].[dbo].[contact_mechanism].[pid] AS [F1], [pgDB].[dbo].[contact_mechanism].[contact_mechanism_type] AS [F2], [pgDB].[dbo].[contact_mechanism].[contact_mechanism_subtype] AS [F3], [pgDB].[dbo].[contact_mechanism].[start_date] AS [F4], [pgDB].[dbo].[contact_mechanism].[end_date] AS [F5], [pgDB].[dbo].[electronic_address].[contact_mechanism_id] AS [F6], [pgDB].[dbo].[electronic_address].[data] AS [F7], [pgDB].[dbo].[phone].[contact_mechanism_id] AS [F8], [pgDB].[dbo].[phone].[area_code] AS [F9], [pgDB].[dbo].[phone].[country_code] AS [F10], [pgDB].[dbo].[phone].[contact] AS [F11], [pgDB].[dbo].[postal_address].[contact_mechanism_id] AS [F12], [pgDB].[dbo].[postal_address].[address_1] AS [F13], [pgDB].[dbo].[postal_address].[address_2] AS [F14], [pgDB].[dbo].[postal_address].[city] AS [F15], [pgDB].[dbo].[postal_address].[state_code] AS [F16], [pgDB].[dbo].[postal_address].[zip] AS [F17] FROM ((( [pgDB].[dbo].[contact_mechanism]  LEFT JOIN [pgDB].[dbo].[electronic_address]  ON  [pgDB].[dbo].[contact_mechanism].[contact_mechanism_id]=[pgDB].[dbo].[electronic_address].[contact_mechanism_id]) LEFT JOIN [pgDB].[dbo].[phone]  ON  [pgDB].[dbo].[contact_mechanism].[contact_mechanism_id]=[pgDB].[dbo].[phone].[contact_mechanism_id]) LEFT JOIN [pgDB].[dbo].[postal_address]  ON  [pgDB].[dbo].[contact_mechanism].[contact_mechanism_id]=[pgDB].[dbo].[postal_address].[contact_mechanism_id]) WHERE ( ( ( [pgDB].[dbo].[contact_mechanism].[pid] = @Pid1)))
Parameter: @Pid1 : Int32. Length: 0. Precision: 10. Scale: 0. Direction: Input. Value: 47.
Walaa avatar
Walaa
Support Team
Posts: 14993
Joined: 21-Aug-2005
# Posted on: 13-Apr-2007 11:09:55   

Actually the fetched ContactMechanismEntities containes the subType entities. i.e. entities inside the collection should be correctly typed.

tangent
User
Posts: 41
Joined: 30-Apr-2006
# Posted on: 13-Apr-2007 17:05:44   

Walaa wrote:

Actually the fetched ContactMechanismEntities containes the subType entities. i.e. entities inside the collection should be correctly typed.

that's just it though, they are not there.. perhaps there is some problem with my generated code? i have searched through EntityClasses/ContactMechanismEntity.cs and can find no reference to any of the subtypes, the only place they are referenced is in RelationClasses/ContactMechanismRelations.cs..

if I remove the TargetPerEntity heirarchy and regenerate the project and then just prefetch on the 1:1 relations between ContactMechanism and its subtypes then everything works as expected, ie if i do

IPrefetchPath2 prefetch = new PrefetchPath2((int)EntityType.PersonEntity); prefetch.Add(PersonEntity.PrefetchPathContactMechanism) .SubPath.Add(ContactMechanismEntity.PrefetchPathPhoneEntity);

then I can access Person.ContactMechanism[0].Phone

but with the inheritance heirarchy in place there is no ContactMechanism.Phone exposed, is this a problem with my generated code or am i still not grasping how to access the subtype data?

Walaa avatar
Walaa
Support Team
Posts: 14993
Joined: 21-Aug-2005
# Posted on: 13-Apr-2007 17:25:34   

I should have been more clear.

then I can access Person.ContactMechanism[0].Phone

This is a refrential relation not an inheritance relation.

You shouldn't find the sub entity as a property inside the super entity, but each item/entity inside the collection is of the subEntity type. example: PhoneEntity phone = (PhoneEntity)ContactMechanism[0]; Even the cast might not be needed.

tangent
User
Posts: 41
Joined: 30-Apr-2006
# Posted on: 13-Apr-2007 17:46:30   

Walaa wrote:

I should have been more clear.

then I can access Person.ContactMechanism[0].Phone

This is a refrential relation not an inheritance relation.

You shouldn't find the sub entity as a property inside the super entity, but each item/entity inside the collection is of the subEntity type. example: PhoneEntity phone = (PhoneEntity)ContactMechanism[0]; Even the cast might not be needed.

ah ok, thanks for clearing that up... how then can I determine which subtype a particular ContactMechanismEntity is of?

ie I fetch all ContactMechanisms but want to bind only the ones that are PhoneEntity to a grid, and display the ones that are AddressEntity somewhere else.. is there an easy way to determine which are which?

Walaa avatar
Walaa
Support Team
Posts: 14993
Joined: 21-Aug-2005
# Posted on: 13-Apr-2007 17:55:23   

You may use an EntityView on the EntityCollection for displaying/databinding and filter the entityView on the EntityType that you want, you may also add any other filtering that you want.

EntityView2 phoneView = new EntityView2(ContactMechanism); phoneView.Filter = new PredicateExpression(PhoneEntity.GetEntityTypeFilter());

tangent
User
Posts: 41
Joined: 30-Apr-2006
# Posted on: 13-Apr-2007 18:03:15   

works perfectly, many thanks Walaa smile

Posts: 23
Joined: 28-Aug-2008
# Posted on: 09-Jun-2009 11:39:36   

tangent wrote:

Walaa wrote:

I should have been more clear.

then I can access Person.ContactMechanism[0].Phone

This is a refrential relation not an inheritance relation.

You shouldn't find the sub entity as a property inside the super entity, but each item/entity inside the collection is of the subEntity type. example: PhoneEntity phone = (PhoneEntity)ContactMechanism[0]; Even the cast might not be needed.

ah ok, thanks for clearing that up... how then can I determine which subtype a particular ContactMechanismEntity is of?

ie I fetch all ContactMechanisms but want to bind only the ones that are PhoneEntity to a grid, and display the ones that are AddressEntity somewhere else.. is there an easy way to determine which are which?

Hi Walaa is there a way to determine which sub type of item in the collection ?

Is that work ? : switch((EntityType)item.offer.LLBLGenProEntityTypeValue) { case EntityType.Sub1Entity: ... case EntityType.Sub2Entity: ... }

Regards...

MTrinder
User
Posts: 1461
Joined: 08-Oct-2008
# Posted on: 09-Jun-2009 20:28:01   

You should be able to use

if (typeof(Item.offer)==ItemType2)
{}

Matt

Posts: 23
Joined: 28-Aug-2008
# Posted on: 09-Jun-2009 21:21:54   

MTrinder wrote:

You should be able to use

if (typeof(Item.offer)==ItemType2)
{}

Matt

Hi Matt ItemType2 is EntityType ? I mean


if (typeof(Item)== EntityType.Sub2Entity)

Note: Not item.offer, my mistake its item, i mean EntityCollection item...

Regards...

MTrinder
User
Posts: 1461
Joined: 08-Oct-2008
# Posted on: 09-Jun-2009 22:19:39   

Exactly - you're comparing the type of the entity - I just used ItemType2 as a placeholder. The type of the entity shuold be in the "EntityType" list.

Posts: 23
Joined: 28-Aug-2008
# Posted on: 10-Jun-2009 08:24:32   

Thanks Matt, i will try this solution and let you know the results.

Regards...

Posts: 23
Joined: 28-Aug-2008
# Posted on: 10-Jun-2009 09:50:25   

MTrinder wrote:

Exactly - you're comparing the type of the entity - I just used ItemType2 as a placeholder. The type of the entity shuold be in the "EntityType" list.

Sorry Matt, but your solution will never work.

For example:


foreach(SuperTypeEntity ste in entity.SuperTypeCollection) {
    if (typeof(ste) == EntityType.Sub2Type) { // Compile time error...
        // Do something...
    }
}

Anyway, even if you get a result from typeof(ste), the result is kind of Type and this is not enum type of EntityType, this is type of class.

For example:


Type t = typeof(Sub2TypeEntity);

Thanks for answering, i see i must figure out my self, how i able to determine EntityType of collection item...

Walaa avatar
Walaa
Support Team
Posts: 14993
Joined: 21-Aug-2005
# Posted on: 10-Jun-2009 10:28:13   

typeof() returns a Type object, which has a property called name, which should give the string name of the class, to compare against.

Also Type has a ToString() method which gives you the fully qualified class name (with namespaces).

Posts: 23
Joined: 28-Aug-2008
# Posted on: 10-Jun-2009 15:49:30   

Thanks Walaa,

Walaa wrote:

typeof() returns a Type object, which has a property called name, which should give the string name of the class, to compare against.

Also Type has a ToString() method which gives you the fully qualified class name (with namespaces).

so it will be like that:


if (item.GetType().Name == EntityType.Sub2Type.ToString()) {
}

isn't that ?

Because you cant use typeof(item), i am sure you know that smile

Thanks again

Walaa avatar
Walaa
Support Team
Posts: 14993
Joined: 21-Aug-2005
# Posted on: 10-Jun-2009 16:29:46   

seems right simple_smile although I didn't try it out myself.

Posts: 23
Joined: 28-Aug-2008
# Posted on: 10-Jun-2009 17:32:42   

Walaa wrote:

seems right simple_smile although I didn't try it out myself.

if item.GetType().Name and EntityType.Sub2Entity.ToString() is equal then:

switch((EntityType)item.LLBLGenProEntityTypeValue) {
    case EntityType.Sub1Entity: ...
    case EntityType.Sub2Entity: ...
}

Must be right, am i wrong ?

I mean;

if we are dealing with Sub2Entity class at the moment it's LLBLGenProEntityTypeValue and (int)EntiyType.Sub2Entity must be equal...

if there is a problem about LLBLGenProEntityTypeValue, we just don't know yet, please give some info...

I wan to remind; we are actually talking about Prefetch Paths and Super Type Entity Collections which may has items from it's Sub Types

Regards...

Walaa avatar
Walaa
Support Team
Posts: 14993
Joined: 21-Aug-2005
# Posted on: 11-Jun-2009 09:05:41   

if item.GetType().Name and EntityType.Sub2Entity.ToString() is equal then:

Code: switch((EntityType)item.LLBLGenProEntityTypeValue) { case EntityType.Sub1Entity: ... case EntityType.Sub2Entity: ... }

Must be right, am i wrong ?

No, you are right.

I mean;

if we are dealing with Sub2Entity class at the moment it's LLBLGenProEntityTypeValue and (int)EntiyType.Sub2Entity must be equal...

Yes they should be equal.

Posts: 23
Joined: 28-Aug-2008
# Posted on: 11-Jun-2009 09:37:12   

Thank you Walaa, i love LLBLGEN Support Team.

But i hate LLBLGEN documentation. There is nothing detailed explained...

Regards...

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39859
Joined: 17-Aug-2003
# Posted on: 11-Jun-2009 09:49:22   

void wrote:

Thank you Walaa, i love LLBLGEN Support Team.

But i hate LLBLGEN documentation. There is nothing detailed explained...

Regards...

huh? it's over 600 printed pages. It would be too detailed if we put in any more details. Sure not everything is documented till the last detail, but that's never the case with any framework (take MSDN for example, there's hardly any in-depth docs besides reference manuals).

You could look at the reference manual as well of our framework which would have given you this property wink (and the generated code contains XML documents which also give you more info if you generate a reference manual from that). It's a lot, I admit, but that also means it takes a lot of time to read everything.

Frans Bouma | Lead developer LLBLGen Pro
Posts: 23
Joined: 28-Aug-2008
# Posted on: 12-Jun-2009 06:06:39   

Otis wrote:

void wrote:

Thank you Walaa, i love LLBLGEN Support Team.

But i hate LLBLGEN documentation. There is nothing detailed explained...

Regards...

huh? it's over 600 printed pages. It would be too detailed if we put in any more details. Sure not everything is documented till the last detail, but that's never the case with any framework (take MSDN for example, there's hardly any in-depth docs besides reference manuals).

You could look at the reference manual as well of our framework which would have given you this property wink (and the generated code contains XML documents which also give you more info if you generate a reference manual from that). It's a lot, I admit, but that also means it takes a lot of time to read everything.

Thank you for explanation, but i don't want to provoke you...

So you admit it, there is a lot of readings and you can never known where to go and find an exact answer.

For example; SaveEntity method. it has 5 overloads. let us take 3. one in this case

SaveEntity(IEntity2 entityToSave, bool refetchAfterSave, bool recursive);

what is exact mean of recursive ? Saves sub entity collections ? (XEntity.YCollection) Saves entities coming from foreign key relation ships ? (XEntity.ZEntity)

I think you are looking to subject from just your perspective...

You know your forum's pages more then your documentation's has. There are lot of subjects in the forum, which are suppose to be in your documentation...

LLBLGEN still best choice, but we love to see some improvement...

Regards...

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39859
Joined: 17-Aug-2003
# Posted on: 12-Jun-2009 10:15:23   

void wrote:

Otis wrote:

void wrote:

Thank you Walaa, i love LLBLGEN Support Team.

But i hate LLBLGEN documentation. There is nothing detailed explained... Regards...

huh? it's over 600 printed pages. It would be too detailed if we put in any more details. Sure not everything is documented till the last detail, but that's never the case with any framework (take MSDN for example, there's hardly any in-depth docs besides reference manuals).

You could look at the reference manual as well of our framework which would have given you this property wink (and the generated code contains XML documents which also give you more info if you generate a reference manual from that). It's a lot, I admit, but that also means it takes a lot of time to read everything.

Thank you for explanation, but i don't want to provoke you... So you admit it, there is a lot of readings and you can never known where to go and find an exact answer.

No I don't admit that there's never an exact answer, I didn't say that. I said there's a lot of information to read and most people won't read everything because it's too much and we don't expect one to do that. That's also why we split up the docs in two: a user manual (the 600+ pages) and a reference manual.

I've read complaints about the docs for years that the docs are not containing everything etc. etc., and frankly, I can't understand most of them: if I compare our documentation with the docs shipped with our competitors, it looks like we ship a full book and they ship a flyer. Remember, all 600+ pages are user documentation, not reference documentation, that's another manual.

For example; SaveEntity method. it has 5 overloads. let us take 3. one in this case SaveEntity(IEntity2 entityToSave, bool refetchAfterSave, bool recursive); what is exact mean of recursive ? Saves sub entity collections ? (XEntity.YCollection) Saves entities coming from foreign key relation ships ? (XEntity.ZEntity)

Let's check the reference manual: recurse When true, it will save all dirty objects referenced (directly or indirectly) by entityToSave also.

So all indirectly referenced entities will also be saved. I'm sorry, but 'recurse' is suggesting a recursive save, and this explanation of indirectly referenced entities also suggests one thing: not only the entity passed in is saved, but also the indirectly referenced entities and the directly referenced entities.

Then check the normal docs: http://www.llblgen.com/documentation/2.6/hh_goto.htm#Using%20the%20generated%20code/Adapter/gencode_usingentityclasses_adapter.htm%23Creatingnewmodifyinganexistingentity

I quote:

Recursive saves are performed by default. This means that the DataAccessAdapter SaveEntity() logic will check whether included entities also have to be saved. In our examples above, this is not the case, but in your own code it can be. If you do not want this, you can specify 'false' for recursive saves in an overload of SaveEntity() in which case only the specified entity will be saved.

So, it's there, but you might not have read it (yet) or overlooked it. That's ok, you can ask questions here and we'll point you to the right page or give you hints etc. We're all developers, we know what we want in documentation, however as the set of features is massive and the material often complex, it's not easy to create documentation everyone will understand: some find it easy, others have a hard time and wonder why the documentation is so complex. There's no solution to this.

I think you are looking to subject from just your perspective...

Of course, that's the only one I can possibly use. Remember, you look at it in a different way than somebody else. You might overlook things (like pointed out above) or misinterpret things other people won't. As we can't look into the heads of everyone, we can't know what can be improved and more importantly: in what way. That's why we tried to explain things first through concepts, so people can learn about the ideas behind the software. The manual isn't build in in this order for nothing. Is it still readable if someone skips the concepts section? I don't know, but should the manual be understandable if someone does? If so, how will you explain ABC if ABC requires you to know what XYZ is first? You explain it there again? No, you either link to the concepts or assume XYZ is understood.

Also keep in mind that our docs were first written in 2003 and have seen improvement over improvement during the years, either through feedback from customers, our own re-reads, when people ask a lot of the same questions here etc. etc. It's not that we look at the docs as "great, we're done, ship it!" and never look back.

You know your forum's pages more then your documentation's has. There are lot of subjects in the forum, which are suppose to be in your documentation...

Every feature is documented, so users can get started. We have the reference manual (several actually) which explain things in detail if you want to look things up like a method. That's the same strategy chosen by Microsoft for example.

LLBLGEN still best choice, but we love to see some improvement...

If something is worded wrong or unclear, we'll rewrite the section(s). However your descriptions are too vague. The features described are sometimes complex, I mean how do you describe advanced prefetch paths to a person who thinks in SQL queries? That's a challenge while a person who thinks in object graphs might understand it after 3 sentences. It's hard to find the middle ground there where most people understand it. Trying to write a manual which explains everything in an understandable fashion so it's understandable for everybody is not possible for these kind of complex systems.

Frans Bouma | Lead developer LLBLGen Pro
Posts: 23
Joined: 28-Aug-2008
# Posted on: 12-Jun-2009 13:16:03   
  1. I am telling you, i never meant to provoke you...

  2. I didn't say there is no exact answer.

So you admit it, there is a lot of readings and you can never known where to go and find an exact answer.

  1. Of course i have read it: (i don't know count, every search of recursive maybe)...

Recursive saves are performed by default. This means that the DataAccessAdapter SaveEntity() logic will check whether included entities also have to be saved. In our examples above, this is not the case, but in your own code it can be. If you do not want this, you can specify 'false' for recursive saves in an overload of SaveEntity() in which case only the specified entity will be saved.

Are you sure is it explain the example ?

  1. Where is the reference manual. I just hearing from you there is a reference manual. If there is one, why it is not part of the full setup. How I able to know there is another documentation ?

  2. I am coming from the Linux world and there is a rule "RTFM". So, I always look the manual first, if there is one...

  3. Even if I wrong, doing a mistake, telling something wrong without knowing, why you have this hostile approach rage Is my illiteracy make me hostile ?

Just tell me, there is a reference manual and where to find it, that's enough for me...

Regards...

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39859
Joined: 17-Aug-2003
# Posted on: 12-Jun-2009 14:40:43   

void wrote:

  1. I am telling you, i never meant to provoke you...
  2. I didn't say there is no exact answer.

So you admit it, there is a lot of readings and you can never known where to go and find an exact answer.

Then we misinterpreted eachother's text.

  1. Of course i have read it: (i don't know count, every search of recursive maybe)...

Recursive saves are performed by default. This means that the DataAccessAdapter SaveEntity() logic will check whether included entities also have to be saved. In our examples above, this is not the case, but in your own code it can be. If you do not want this, you can specify 'false' for recursive saves in an overload of SaveEntity() in which case only the specified entity will be saved.

Are you sure is it explain the example ?

Which example are you referring to exactly? You asked a question about SaveEntity that was a bit unclear what everything was for. I tried to illustrate that the documentation is there, but as I also tried to describe, the volume of information can be a bit overwhelming and you might have looked in the wrong direction. This isn't necessarily the fault of the documentation, it's more that every reader might look for something different and thus for every reader a path should be available to the information s/he's looking for. That path might not be there or might be unclear. In those cases, a reader gets lost in the documentation and doesn't know where to look and gives up.

  1. Where is the reference manual. I just hearing from you there is a reference manual. If there is one, why it is not part of the full setup. How I able to know there is another documentation ?

It IS part of the full setup. It's also mentioned in the manual . In your installation folder there's a folder called 'Reference Manuals'. Browse to either .NET 1.x or .NET 2.x and use the readme.txt to run the proper register command to merge the docs into vs.net. You can also download a .chm version btw: http://www.llblgen.com/pages/documentation.aspx or the customer area also has the .chm file. This might be more convenient, as it's a separate file and you don't have to read it in vs.net.

The reference manuals are very big, so we decided to ship only the vs.net versions and left the .chm file for download. This also means that the reference manual should be installed manually, which is a bit of a bummer, though we don't want to do that automatically as it causes vs.net's help system to re-index which can take 10 minutes or longer and we don't want to force that upon people.

The runtime libs also come with .xml files which should give you tooltip documentation in intellisense in vs.net, so for example if you do cntrl-shift-space inside SaveEntity() in the C# editor you should see documentation on 'recurse'.

  1. I am coming from the Linux world and there is a rule "RTFM". So, I always look the manual first, if there is one...

I'm familiar with the concept, but as I tried to explain, we don't blame you if you can't find something in the manual, that's why this forum is here and we're here to help you out. So if I made that impression, that's not what I meant, on the contrary.

  1. Even if I wrong, doing a mistake, telling something wrong without knowing, why you have this hostile approach rage Is my illiteracy make me hostile ?

As I said above, I think we misinterpreted eachother's text. We spend over a man-year of work in the manual alone, and we know it's not perfect as it can never be perfect. So in a way it's a loose-loose situation for us as there's always a way to get lost in the docs, be it because we didn't set it up properly or because the reader thought something was located at spot X but it was described at spot Y and lead to frustration. If someone then says "improvement is necessary" that's not something we can work with, as we already invested a lot of time in it and a general remark like 'improvement is necessary', although appreciated wink , it's not giving us information about what should be improved. We can't rewrite all 600 pages, even though some should be rewritten.

So we want to cause as less frustration with the docs as possible, however if you or someone else has feedback on the docs, please be specific, as it's otherwise undoable for us to improve the docs.

Frans Bouma | Lead developer LLBLGen Pro
Posts: 23
Joined: 28-Aug-2008
# Posted on: 12-Jun-2009 15:20:34   

Thank you, for your explanation.

I have limited time for now, but i will be back for explanation what improvements, i am talking about.

At the end, i mean you are doing good job in this forum, but that shouldn't be necessary for things like information...

I am sorry for my English, i can't explain my mind exactly. But believe me, I had lots of experience in that IT world, not only software development, i really mean the IT world.

Your documentations has foreign accent. Don't blame me, I think like that, I know you never accept, am just telling... (No need to write a reply full of a page)

Regards and best wishes smile

1  /  2