Inheritance preview

Posts   
 
    
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39774
Joined: 17-Aug-2003
# Posted on: 25-May-2005 17:40:36   

simple_smile

Ok, first killer feature is now working in the developer branch of 1.0.2005.1 (the upgrade currently in development).

It finds inheritance trees automatically for table-per-concrete-entity hierarchies simple_smile The DB has a table for employee, manager, boardmember and clerk. It also has a table for companycar, which is a table-per-entity-hierarchy entity, and I've to add that code yet.

Below, first you'll see the project right after it's created. No hierarchy defined. You can manually add / remove an entity to a supertype, but it's far more efficient to let software find that out, right? smile . Well, on the second screenshot, you see the option selected and on the 3rd shot, you'll see the result after that! simple_smile . Magic huh wink

You'll also notice relations on which the hierarchy is build on are no longer visible.

Frans Bouma | Lead developer LLBLGen Pro
jeffreygg
User
Posts: 805
Joined: 26-Oct-2003
# Posted on: 25-May-2005 18:48:22   

oooooo...niiiiiiice, Frans! Automagical, even. smile

Jeff...

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39774
Joined: 17-Aug-2003
# Posted on: 25-May-2005 19:18:25   

simple_smile

Yeah, it's going to be great! Much more to come on the inheritance front (derived entities created in the designer with solely expression columns etc. simple_smile )

I'll support 2 inheritance types, out of the 3 common. The one I won't support is table per entity type, where fields from a parent entity's table are copied into the child table as well. This is bad schema design and a problem to keep everything in sync so I've dropped that.

Also mixing of inheritance types in a hierarchy isn't supported, though I don't foresee that as a problem either. simple_smile

Frans Bouma | Lead developer LLBLGen Pro
alexdresko
User
Posts: 336
Joined: 08-Jun-2004
# Posted on: 25-May-2005 19:32:11   

Holy cow, Batman! That's rad!

alexdresko
User
Posts: 336
Joined: 08-Jun-2004
# Posted on: 26-May-2005 03:15:43   

Did I mention how cool that is? Here I am, many hours since the previous post, and I'm still thinking about it. I've got a project coming up that'll be a great test!

takb
User
Posts: 150
Joined: 12-Mar-2004
# Posted on: 26-May-2005 07:54:43   

Looking great, can't wait! This is going to help us a lot. In fact, we're trying to hold off some functionality in our next release to coincide with your inheritance features as this feature will save us a lot of time.

What about inheritance of typed lists?

We currently have our own support classes to basically achieve this (see below). What we need to do is extend base typed lists with additional fields and filters. Sometimes we also extend base typed lists with some predicates but I guess this would be difficult to do (and not as important for us).

Our base class:


namespace MyProj.UntypedListClasses
{
    [Serializable]
    public abstract class UntypedListBase : TypedListBase
    {
        private ResultsetFields fields;
        private IRelationPredicateBucket filterBucket;

        protected UntypedListBase()
        {
            fields = new ResultsetFields(FieldCount);
            filterBucket = new RelationPredicateBucket();
            DefineFields();
            DefineRelations();
        }

        protected UntypedListBase(SerializationInfo info, StreamingContext context) : base(info, context)
        {
        }

        // These aren't abstract so that derived classes always follow the same implementation pattern
        // That is, derived classes always call base... before doing their own thing
        protected virtual void DefineFields() {}
        protected virtual void DefineRelations() {}

        #region Properties
        protected virtual int FieldCount
        {
            get { return 0; }
        }

        public ResultsetFields Fields
        {
            get { return fields; }
        }

        public IRelationCollection Relations
        {
            get { return FilterBucket.Relations; }
        }

        public IRelationPredicateBucket FilterBucket
        {
            get { return filterBucket; }
        }

        #endregion

        public IRelationPredicateBucket GetRelationInfo()
        {
            return filterBucket;
        }

        public IEntityFields2 GetFieldsInfo()
        {
            return fields;
        }

        #region ITypedListCore Members

        public override int Count
        {
            get { return this.Rows.Count; }
        }

        #endregion
    }
}

Then we can go:


namespace MyProj.UntypedListClasses
{
    public class PackageListUntypedList : UntypedListBase
    {
        private static int fieldCount = 54;

        public PackageListUntypedList()
        {
            this.TableName = "PackageList";
        }
        
        protected PackageListUntypedList(SerializationInfo info, StreamingContext context) : base(info, context)
        {
        }
    
        protected override int FieldCount
        {
            get { return fieldCount + base.FieldCount; }
        }

        protected override void DefineFields()
        {
            base.DefineFields();
            int i = base.FieldCount;
            Fields.DefineField(DOCUMENTBASEFieldIndex.DOCUMENTKEY, i++, "DOCUMENTBASE_DOCUMENTKEY");
            Fields.DefineField(DOCUMENTBASEFieldIndex.PUBLISHDATE, i++, "DOCUMENTBASE_PUBLISHDATE");
...etc...
        }

        protected override void DefineRelations()
        {
            base.DefineRelations();
            Relations.Add(DOCUMENTBASEEntity.Relations.ACCOUNTINGDOCUMENTEntityUsingDOCUMENTBASEID, JoinHint.Left);
            Relations.Add(DOCUMENTBASEEntity.Relations.PACKAGEEntityUsingDOCUMENTBASEID);
...etc...
        }
    }
}

and then we can derive again:


namespace MyProj.UntypedListClasses.ARUntypedList
{
    [Serializable]
    public class ARPackageListUntypedList: PackageListUntypedList
    {
        private static int fieldCount = 2;

        public ARPackageListFullDetailsUntypedList()
        {
        }
        protected ARPackageListFullDetailsUntypedList(SerializationInfo info, StreamingContext context) : base(info, context)
        {
        }

        protected override int FieldCount
        {
            get { return base.FieldCount + fieldCount; }
        }

        protected override void DefineFields()
        {
            base.DefineFields ();
            int i = base.FieldCount;
            Fields.DefineField(AGENTFieldIndex.AGENTKEY, i++, "AGENT_AGENTKEY");
            Fields.DefineField(AGENTFieldIndex.NAME, i++, "AGENT_NAME");
        }

        protected override void DefineRelations()
        {
            base.DefineRelations();

            Relations.Add(CONSUMEREntity.Relations.CONSUMERAGENTEntityUsingCONSUMERID);
            Relations.Add(CONSUMERAGENTEntity.Relations.AGENTEntityUsingAGENTID);
            Relations.Add(AGENTEntity.Relations.AGENTREPRESENTATIVEEntityUsingAGENTID);
            Relations.Add(AGENTREPRESENTATIVEEntity.Relations.COREUSEREntityUsingCOREUSERID);
        }
    }
}

MacDennis avatar
MacDennis
User
Posts: 50
Joined: 03-May-2005
# Posted on: 26-May-2005 10:49:45   

Great feature!

How does the designer discover the sub-types? Maybe by finding a field like Clerk.ParentEmployeeId ?

Dennis

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39774
Joined: 17-Aug-2003
# Posted on: 26-May-2005 11:42:39   

@takb: inheritance of typed lists is not going to happen in the designer. Though enhancements to the typed list editor are planned as well simple_smile

You can expand existing typed lists already in code. Use the Expand method on teh fields list, then add your own in the override of the routines which build the fields list and relation list.

@MacDennis: I'll keep that under wraps until it's released wink You'll never know who's reading here wink

Frans Bouma | Lead developer LLBLGen Pro
NickD
User
Posts: 224
Joined: 31-Jan-2005
# Posted on: 26-May-2005 17:46:49   

I'm going to ask the question that will reveal my level of competence on this issue, but how does this help?

I understand from an OO point of view why this is good, but how does this help on the backend? Obviously I'm missing some major connection here. I totally understand that the example above of (employee, manager, board member, clerk) is for concept only. But, in my trying to understand this, I have to go with what I know. So, I continue the process. If the Employee table is the base table, and clerk is a child to that, then wouldn't you have a table for every job description? That seems foolish. I understand the manager and board member tables, but still could you make the argument that any of the columns that are included in the Manager table could just as easily be stored in the Employee table and left null if that Employee record is not a manager?

I guess I am not seeing where the benefit of this is at the database level.

P.S. Make sure to speak slowly and use small words smile

JimFoye avatar
JimFoye
User
Posts: 656
Joined: 22-Jun-2004
# Posted on: 26-May-2005 18:15:28   

Hey Frans I believe this directly addresses one of the points my offshore team was making about NHibernate, that is does this kind of inheritance.

alexdresko
User
Posts: 336
Joined: 08-Jun-2004
# Posted on: 26-May-2005 18:30:29   

Nick,

For some situations, the method you suggested works perfectly fine. The problem arises when the subclasses are drastically different from the parent class. A single table with 80 fields isn't exactly easy to work with. simple_smile I believe the inheritance scenario is also useful when new sub classes need to be introduced, especially if the sub class has fields that don't allow NULL values.

Alvaro
User
Posts: 52
Joined: 01-Jun-2004
# Posted on: 26-May-2005 18:33:58   

NickD wrote:

I'm going to ask the question that will reveal my level of competence on this issue, but how does this help?

I understand from an OO point of view why this is good (...) then wouldn't you have a table for every job description? That seems foolish. (...) any of the columns that are included in the Manager table could just as easily be stored in the Employee table and left null if that Employee record is not a manager?

You should read Ambler's work on this, for example here http://www.agiledata.org/essays/mappingObjects.html#MappingInheritance. He explains it way better than me.

As a humble preview, the option of storing all subtyes in the same table is possible and sometimes the best, however as everything in software there are advantages and disadvantages which I assure you Ambler discusses properly in thatl link.

cheers alvaro.-

psandler
User
Posts: 540
Joined: 22-Feb-2005
# Posted on: 26-May-2005 20:14:06   

Alvaro wrote:

You should read Ambler's work on this, for example here http://www.agiledata.org/essays/mappingObjects.html#MappingInheritance. He explains it way better than me.

I just read through the section of that article you linked to. Interesting stuff.

One of the things that concerns me about OR mapping is that it will make it easier for developers to bastardize relational theory. This section in particular worries me:

http://www.agiledata.org/essays/mappingObjects.html#MapToGenericStructure

Metadata-based relational models? frowning

I'm quite sure this is not the direction Frans is going, though. simple_smile

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39774
Joined: 17-Aug-2003
# Posted on: 27-May-2005 11:37:26   

NickD wrote:

I'm going to ask the question that will reveal my level of competence on this issue, but how does this help?

In a way it does, but it has a 'dark' side stuck_out_tongue_winking_eye . In the example above, what if a 'clerk' is the manager of the clerks? Then it's 2 types. Which requires multiple inheritance. So in a way the datamodel has to be setup properly and not change.

I understand from an OO point of view why this is good, but how does this help on the backend? Obviously I'm missing some major connection here. I totally understand that the example above of (employee, manager, board member, clerk) is for concept only. But, in my trying to understand this, I have to go with what I know. So, I continue the process. If the Employee table is the base table, and clerk is a child to that, then wouldn't you have a table for every job description? That seems foolish. I understand the manager and board member tables, but still could you make the argument that any of the columns that are included in the Manager table could just as easily be stored in the Employee table and left null if that Employee record is not a manager?

I guess I am not seeing where the benefit of this is at the database level.

P.S. Make sure to speak slowly and use small words smile

Well, it allows you to add relations to types which you would otherwise add to generic types. For example, otherwise you probably have an employee table, and because the boardmember has a relation with companycar, the relation between employee and companycar was made, though that relation is only valid for boardmembers. With modelling subtypes in different tables, you can do that AND use them properly in your code, i.e.: a boardmemberclass has the employee relations (!) and also the boardmember relations (!) but the manager doesn't have the company car relation (which is exclusive for boardmembers).

JimFoye wrote:

Hey Frans I believe this directly addresses one of the points my offshore team was making about NHibernate, that is does this kind of inheritance.

In a way it will, though a pure domain model will still be a bit different simple_smile But at least it will address the inheritance thing simple_smile

Frans Bouma | Lead developer LLBLGen Pro
NickD
User
Posts: 224
Joined: 31-Jan-2005
# Posted on: 27-May-2005 20:55:50   

Alvaro wrote:

You should read Ambler's work on this, for example here http://www.agiledata.org/essays/mappingObjects.html#MappingInheritance. He explains it way better than me.

Good article! Thanks. I think I am starting to see what the point is. I realized at the beginning of the article that I tend to let my database design determine how my data is "handled." Meaning that I start with my database design FIRST because I like to have my data ducks in a row before I start playing with objects. But, I can see how this approach can lead to missed elements. I really like Terry Halpin's ORM and it has definitely changed how I design my data model. This is definitely more food for thought.

takb
User
Posts: 150
Joined: 12-Mar-2004
# Posted on: 03-Jun-2005 05:34:20   

Sorry for the delay in responding...

Otis wrote:

@takb: inheritance of typed lists is not going to happen in the designer. Though enhancements to the typed list editor are planned as well simple_smile

You can expand existing typed lists already in code. Use the Expand method on teh fields list, then add your own in the override of the routines which build the fields list and relation list.

Yes, I've just had a look and found the new "Expand" method! (It wasn't there when I first needed typed list inheritance. But we've just upgraded to 1.2004.2 for our next release and so are discovering all the neat new things you've added since the version that we were using which was from October or November last year). So sure, that would help simplify what I want to achieve and will be sufficient for what we need for now.

Although, I still think typed list inheritance would be useful since by going the "expand" method, I lose the automatically generated typed aspect of the "Row" class. I guess I could manually extend this class in my inherited typed list but that's less than ideal. In fact, with a large number of fields, we'd probably stick with calling them untyped lists and just treating them like plain untyped datasets.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39774
Joined: 17-Aug-2003
# Posted on: 03-Jun-2005 09:10:45   

takb wrote:

Sorry for the delay in responding...

Otis wrote:

@takb: inheritance of typed lists is not going to happen in the designer. Though enhancements to the typed list editor are planned as well simple_smile

You can expand existing typed lists already in code. Use the Expand method on teh fields list, then add your own in the override of the routines which build the fields list and relation list.

Yes, I've just had a look and found the new "Expand" method! (It wasn't there when I first needed typed list inheritance. But we've just upgraded to 1.2004.2 for our next release and so are discovering all the neat new things you've added since the version that we were using which was from October or November last year). So sure, that would help simplify what I want to achieve and will be sufficient for what we need for now.

Although, I still think typed list inheritance would be useful since by going the "expand" method, I lose the automatically generated typed aspect of the "Row" class. I guess I could manually extend this class in my inherited typed list but that's less than ideal. In fact, with a large number of fields, we'd probably stick with calling them untyped lists and just treating them like plain untyped datasets.

You have a point. I have to see if I can cram it in. I won't promise anything, though.. simple_smile

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39774
Joined: 17-Aug-2003
# Posted on: 13-Jun-2005 21:23:12   

Tomorrow I hope to have some kick ass screenshots of the inheritance visualizer (in the entity editor, you'll see an inheritance graph using VS.NET 2005-style objects.). You won't believe your eyes simple_smile

All made possible through Netron: http://netron.sourceforge.net/

Frans Bouma | Lead developer LLBLGen Pro
swallace
User
Posts: 648
Joined: 18-Aug-2003
# Posted on: 13-Jun-2005 22:08:42   

Oooh, eye candy. That NetronGraphLib is sweet. smile

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39774
Joined: 17-Aug-2003
# Posted on: 13-Jun-2005 22:53:19   

swallace wrote:

Oooh, eye candy. That NetronGraphLib is sweet. smile

It's more than sweet, I can tell you simple_smile This offers so much options for enhancements, incredible simple_smile This library deserves a front-seat in the .NET library discussions, it's a kick-ass piece of work and very extensible, just with a few lines of code simple_smile

Frans Bouma | Lead developer LLBLGen Pro
Devildog74
User
Posts: 719
Joined: 04-Feb-2004
# Posted on: 14-Jun-2005 01:21:17   

very nice indeed.