Table-per-subclass?

Posts   
1  /  2
 
    
ChristianD
User
Posts: 7
Joined: 25-Jul-2006
# Posted on: 25-Jul-2006 17:13:47   

Does LLBLGen support table-per-subclass inheritance mapping?

e.g.

ParentTable -CHildTable1 -ChildTable2

Parent maps 1:1 with each child

If it does will it support mapping collections of the subclass?

e.g.

Someclass{

private IList _childTable1Collection private IList _childTable2COllection

Thanks in advance.

Christian

Jessynoo avatar
Jessynoo
Support Team
Posts: 296
Joined: 19-Aug-2004
# Posted on: 25-Jul-2006 17:35:24   

_TargetPerEntity _ inheritence is supported by llblgen and corresponds to what you call table-per-subclass inheritence.

In the designer, you will be able to let LLBLGen discover all the pk-pk/fk relations corresponding to hierarchies, keep those you wish to use, and then the generator will build for the child tables inherited entities, which can be manipulated as a agregation of the parent table and the child table.

You can deal with collections, relations prefetchpaths and all the standard features transparently just as with regular entity, since all the specific plumbing is abstracted from you.

generics can make your collection specific, or you can keep them generic.

ChristianD
User
Posts: 7
Joined: 25-Jul-2006
# Posted on: 25-Jul-2006 17:45:54   

Yeah, I have just been playing with the designer and i must say I am very impressed so far.

The mapping of the collections I am referring to isn't a simple Parent-Child relationship.

In my example (i'll use real entity names) Contact which is parent to PostalAddress is the root in the hierarchy. I don't want to map to collections of type Contact. I want to map collections of the subtypes. PostalAddress cannot be associated through itself. The connection is through the super type. Person->COntact->PostalAddress

Does this make sense? Can LLBLGen handle this? I ask because I have tried with other ORM tools and they cannot as far as I have been able to determine.

Posts: 1251
Joined: 10-Mar-2006
# Posted on: 25-Jul-2006 19:24:41   

Yes, I believe you can do what you are asking. You can mark the top entities as Abstract to keep them from being created if necessary.

ChristianD
User
Posts: 7
Joined: 25-Jul-2006
# Posted on: 25-Jul-2006 20:07:01   

WayneBrantley wrote:

Yes, it believe you can do what you are asking. You can mark the top entities as Abstract to keep them from being created if necessary.

Thanks for the response, but i need a more concrete answer than that. I need to know absolutely if i can or can't.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 25-Jul-2006 21:39:15   

Target per subclass == Hierarchy of type TargetPerEntity (see concepts documenation). I have no idea what you mean with 'If it does will it support mapping collections of the subclass?', could you elaborate a bit on that? simple_smile

Frans Bouma | Lead developer LLBLGen Pro
ChristianD
User
Posts: 7
Joined: 25-Jul-2006
# Posted on: 25-Jul-2006 22:00:33   

Otis wrote:

Target per subclass == Hierarchy of type TargetPerEntity (see concepts documenation). I have no idea what you mean with 'If it does will it support mapping collections of the subclass?', could you elaborate a bit on that? simple_smile

I'll give you an example:

TableA is a super class to ChildTable1 and ChildTable2

TableC is a 1 to many to TableA.

TableA maps to an abstract type. I want to be able to create a collection of the Subtypes that map to ChildTable1 and ChildTable2.

Can LLBLGen figure out that to map a collection of ChildTable1 or ChildTable2 it needs to go through the supertype TableA?

I hope thats clear.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 25-Jul-2006 22:44:47   

If tableC has a relation with TableA, you can't define that TableC has a specific relation with childtable1 OR childtable2, as it has a relation with tableA. TableC thus has a collection with TableA's, which can be of type childtable1 or childtable2 (as you marked TableA abstract).

if you want tableC to have a relation with childtable1, you have to create that relation directly, and remove the relation tableA -> tableC.

You of course COULD fill the tableC.TableAs collection with solely childtable1's, by specifying a typefilter when you fetch the TableA instances., but it would be incorrect to define a relation TableC - Childtable1 over TableC - TableA, as that last relation suggest more than the relation you want to define.

Frans Bouma | Lead developer LLBLGen Pro
ChristianD
User
Posts: 7
Joined: 25-Jul-2006
# Posted on: 25-Jul-2006 22:59:48   

Let me give you a practical example.

I have the following classes: Person, Contact, Phone, Address

Contact is a supertype to both PhoneNumber and Address. (TargetByENtity) A Person has a collection of PhoneNumber and Address.

In the database the Contact has an FK to the Person table. You can't go directly from Person to PhoneNumber or Address. You can only get there through Contact.

Hopefully this will allow you to more clearly answer my question. I have looked at a leading OSS product and it can't do this.

THanks,

Christian

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 26-Jul-2006 12:11:28   

ChristianD wrote:

Let me give you a practical example.

I have the following classes: Person, Contact, Phone, Address

Contact is a supertype to both PhoneNumber and Address. (TargetByENtity) A Person has a collection of PhoneNumber and Address.

In the database the Contact has an FK to the Person table. You can't go directly from Person to PhoneNumber or Address. You can only get there through Contact.

Correct. This thus means that there's a relation in llblgen pro between Contact and Person and through that relation you can fetch polymorphically all contacts as their right type, address or Phonenumber in the Contacts collection in Person. This is because Person doesn't have a relation with Address, it has a relation with Contact.

If you want to load the Person's Addresses, you could do that in LLBLGen Pro, by adding a type filter (see: Using the generated code -> Selfservicing/adapter -> Filtering and sorting -> Advanced filter usage -> Filtering on entity type) to the filter used to fetch the related contacts. This isn't automatic as there's no relation between person and address.

Hopefully this will allow you to more clearly answer my question. I have looked at a leading OSS product and it can't do this.

THe only 'leading' oss solution I can think of is nhibernate and it indeed can't do it as well, simply because it's not correct what you want to do. I hope I have explained it well enough. simple_smile

Frans Bouma | Lead developer LLBLGen Pro
ChristianD
User
Posts: 7
Joined: 25-Jul-2006
# Posted on: 26-Jul-2006 16:07:33   

Thanks for your response. I will have to work a little with the demo of LLBLGEN and see what I can accomplish.

What do you mean by "it's not correct what you want to do"? Is there a correct way to model this situation?

Christian

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 26-Jul-2006 16:23:25   

ChristianD wrote:

What do you mean by "it's not correct what you want to do"? Is there a correct way to model this situation? Christian

The situation you want is only possible if there's a relation between Person and Address directly. This requires an FK in Address to Person. This could be added of course simple_smile and this will lead to an Addresses collection in Person. However fetching the collection won't filter on Addresses, you've to specify the filter for the type manually.

It's not correct to use the Person - Contact relation for a relation between Person and Address.

Frans Bouma | Lead developer LLBLGen Pro
simmotech
User
Posts: 1024
Joined: 01-Feb-2006
# Posted on: 26-Jul-2006 17:13:25   

ChristianD wrote:

Thanks for your response. I will have to work a little with the demo of LLBLGEN and see what I can accomplish.

What do you mean by "it's not correct what you want to do"? Is there a correct way to model this situation?

Christian

I think everyone agrees that Person->Address is not directly possible in the database. (And so Person->PhoneNumber is not directly possible for the same reason)

However, you do want your generated PersonEntity to have a list of Addresses (and list of PhoneNumbers presumably)

The relationship between Person and Contact is defined however so in the GUI you will be able to get a collection of Contacts which, by polymorphism, will contain Addresses and PhoneNumbers

Now if you add a property to PersonEntity called Addresses which creates a view from the already existing Contacts property and filters only the addresses (using the type filter that Frans mentioned), I think you will get what you want.

Repeat the above for PhoneNumbers and you will then have three properties on PersonEntity. One returning a collection of both Addresses and PhoneNumbers and two returning views on that same collection but filtering to return one specific type.

I don't think I've said anything new here but maybe different wording will make something click. (On the other hand maybe I'm talking rubbish since I've not actually tried this confused )

Cheers Simon

ChristianD
User
Posts: 7
Joined: 25-Jul-2006
# Posted on: 26-Jul-2006 17:20:04   

Thanks Simon. I am actually prototyping what you speak of.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 26-Jul-2006 17:30:24   

You can have the collection generated for you if you want: create a custom relation in person to Address where person is on the PK side and as FK field the Contact FK field to person. simple_smile

Frans Bouma | Lead developer LLBLGen Pro
JuergenF
User
Posts: 29
Joined: 23-May-2006
# Posted on: 04-Aug-2006 12:38:08   

Hi, Sorry to warm this thread up, but

create a custom relation in person to Address where person is on the PK side and as FK field the Contact FK field to person.

How?

My Test-DB is based on your diagram in Help / 'Hierarchy creation for proper entity relation modelling' I want to know wich managers work in a department.

If I add a custom relation for this on department a) If I check 'Also add this relation to the related entity' I get a compiler error Type "Test.RelationClasses.ManagerRelations" already contains a Definition for "DepartmentEntityUsingWorksForDepartmentId". b) If I don't check this option the compiler complains '"Test.CollectionClasses.ManagerCollection" has no Definition for "GetMultiManyToOne".' (Error-messages translated from german)

And if I do someting like Department.GetMultiEmployee() with a type-filter I only get employees, and can't cast them to managers...

The only thing I get to work is 'indirect' as in managerCollection.GetMulti(ManagerFields.DepartmentId == whateverDepartment.Id)

Any further hints?

TIA Juergen

Jessynoo avatar
Jessynoo
Support Team
Posts: 296
Joined: 19-Aug-2004
# Posted on: 04-Aug-2006 16:19:48   

a) If I check 'Also add this relation to the related entity' I get a compiler error Type "Test.RelationClasses.ManagerRelations" already contains a Definition for "DepartmentEntityUsingWorksForDepartmentId".

This is normal since the child class inherits the relations from the parents and Employee has the relation DepartmentEntityUsingWorksForDepartmentId.

b) If I don't check this option the compiler complains '"Test.CollectionClasses.ManagerCollection" has no Definition for "GetMultiManyToOne".'

Would you agree to send us the lgp project corresponding, since we should be able to reproduce the problem straight away. You may keep only the 3 tables of the situation.

if I do someting like Department.GetMultiEmployee() with a type-filter I only get employees, and can't cast them to managers

Can you post the code of that query, especially the bit of the filter, since it is something that should work.

Thkx

JuergenF
User
Posts: 29
Joined: 23-May-2006
# Posted on: 04-Aug-2006 17:05:30   

Would you agree to send us the lgp project corresponding, since we should be able to reproduce the problem straight away.

Of course. Where should I send it?

You may keep only the 3 tables of the situation.

This is a pure test-project. There are no more tables wink

Can you post the code of that query, especially the bit of the filter, since it is something that should work.

something like

            
DepartmentEntity dep = new DepartmentEntity(1);
ManagerCollection mc = (ManagerCollection)dep.GetMultiEmployee(true, ManagerEntity.GetEntityTypeFilter());

The 2nd line indicates what I'd like to do so I can work with the manager's fields - but this results in a compiler error (of course) But if the one-side custom-relation in departments would work, I'd not need this at all anyway...

Thanks, Juergen

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 05-Aug-2006 20:39:07   

Please send your lgp file to support AT llblgen.com and we'll have a look.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 07-Aug-2006 17:30:05   

JuergenF wrote:

Would you agree to send us the lgp project corresponding, since we should be able to reproduce the problem straight away.

Of course. Where should I send it?

You may keep only the 3 tables of the situation.

This is a pure test-project. There are no more tables wink

Ok, the compile error you get with the relations is caused by the fact that there will be two fields mapped onto a relation in Manager which are both called 'Department'. You should rename one. These don't override eachother, so the relation in Manager doesn't override the relation in employee, because the relations are different.

Also, looking at your project model, the relation between manager and department is redundant, it already inherits that relation from Employee.

The model in the docs uses a different relation: from manager to department for 'ManagesDepartment', as Manager already inherits WorksForDepartment from employee.

Can you post the code of that query, especially the bit of the filter, since it is something that should work.

something like

            
DepartmentEntity dep = new DepartmentEntity(1);
ManagerCollection mc = (ManagerCollection)dep.GetMultiEmployee(true, ManagerEntity.GetEntityTypeFilter());

The 2nd line indicates what I'd like to do so I can work with the manager's fields - but this results in a compiler error (of course) But if the one-side custom-relation in departments would work, I'd not need this at all anyway...

The GetMultiEmployees returns an employees collection, as it is a relation with employees. The filter you passed wont change the return type of the method. What it does though is that all employee entity instances in the collection returned will be managers.

You'll get an employees collection as the relation is defined on the level department - employee, not via a subtype of employee.

Frans Bouma | Lead developer LLBLGen Pro
JuergenF
User
Posts: 29
Joined: 23-May-2006
# Posted on: 07-Aug-2006 18:36:29   

Ok, the compile error you get with the relations is caused by the fact that there will be two fields mapped onto a relation in Manager which are both called 'Department'.

I thought there wouldn't be 2 fields in manager, if I uncheck 'Also add this relation to the related entity'. I've read you can't have one-sided relations in SelfServicing code, but hoped wink the code for the 'other side' would be there already from inheritance.

Also, looking at your project model, the relation between manager and department is redundant, it already inherits that relation from Employee.

I don't want to create another way for the manager to get his department, I'm interested in the other side: I'd like to start with the department and have a field to fetch all managers working there - and have manager-entities, not just employees.

But anyway, I can just fill a manager-collection the 'traditional' way with

managerCollection.GetMulti(ManagerFields.DepartmentId == whateverDepartment.Id)

as I said...

Thanks Juergen

Jessynoo avatar
Jessynoo
Support Team
Posts: 296
Joined: 19-Aug-2004
# Posted on: 08-Aug-2006 11:34:57   

I think you should indeed get rid of the second relation if it's got the same semantics as the employee-department relation.

With a single relation employee-department, you'll be able to get what you want, starting from department to employee and using an entitytype filter to retrieve the managers only.

JuergenF
User
Posts: 29
Joined: 23-May-2006
# Posted on: 08-Aug-2006 17:49:20   

With a single relation employee-department, you'll be able to get what you want, starting from department to employee and using an entitytype filter to retrieve the managers only.

Yes, but they are still employees, I don't get the additional manager-fields with them...

Anyhow, now I know a bit more what works and what doesn't, so I'll stop this for now - but I'm already creating a small test-project for the next problem I ran into. You'll see me again, soon ;-)))

Thanks Juergen

Posts: 1251
Joined: 10-Mar-2006
# Posted on: 28-Sep-2006 06:34:36   

Warming this thread up......I had this same problem and am trying to summarize the conclusions from above.

1) When adding a custom relation, you cannot uncheck the 'Also add this relation to the related entity'. If you do, the code will not compile. There is no workaround - just don't uncheck that box.

2) The reason I would want to uncheck the box in #1 above, is because the entity I am relating it to has already inherited this relationship as it is part of a TargetPerEntity hierarchy. Letting it add this relationship results in duplicate unused code - and by default names the property the same as an already existing property causing a compile error. (This is of course fixed by renaming the property on the designer).

Is that pretty much the case?

*Edit: I have a relationship EntityA to EntityB 1-n. EntityB is part of a hierarchy with EntityC a child of that hierarchy. So, when I add a relationship to EntityA for EntityC, I am still getting a compile error even if I do not uncheck that box. I am getting a duplicate IEntityRelation name. In the EntityCRelations.cs file, I have TWO relations of EntityAUsingEntityAPKey.

So, nothing working for me...for now, I am commenting out this extra relation when I build.

Walaa avatar
Walaa
Support Team
Posts: 14946
Joined: 21-Aug-2005
# Posted on: 28-Sep-2006 09:02:34   

So, when I add a relationship to EntityA for EntityC, I am still getting a compile error even if I do not uncheck that box. I am getting a duplicate IEntityRelation name. In the EntityCRelations.cs file, I have TWO relations of EntityAUsingEntityAPKey.

I think you should not add that relation. As it already exists through the EntityC Parent (EntityB).

1  /  2