Inheritance thru tiers

Posts   
 
    
ShaneN
User
Posts: 3
Joined: 04-Jan-2007
# Posted on: 05-Jan-2007 12:19:25   

LLBLGen Version: 2.0.0.0 Final Database: Sql Server 2000 Template group: Adpater Lanaguage: C# Platform: .Net 2

These are follow-on questions to the 'Inheritance thru tiers' question by John Gordon (a colleague).

http://www.llblgen.com/tinyforum/Messages.aspx?ThreadID=8308

We've created Factory classes as suggested (below is the factory class for the People class).

Question 1 In the PeopleFactory class we've inherited from the PersonalEntityFactory and overridden methods and properties where required. Would you recommend this or to inherit directly from IEntityFactory2 and add all required methods and properties?

Question 2 In the PeopleFactory class we're using the EntityType 'People' and we're also using the EntityName 'People'. To ensure that intances of the People class get created correctly we've also modified the CreateEntityFieldsObject and CreateFields methods in Dal.FactoryClasses.EntityFieldsFactory to take account of the People EntityType and entity name. And we've obviously modified the Dal.EntityType to include 'People'.

This works fine but the question is how do we keep our changes when we re-generate the Dal code (which we obviously need to do when adding new entities and modifiying existing ones)? We've tried using user comment regions to no avail. Or is there an alternate approach you'd recommend?

PeopleFactory class:


using System.Collections.Generic;
using BusinessTier.Contacts;
using Dal;
using Dal.FactoryClasses;
using Dal.HelperClasses;
using SD.LLBLGen.Pro.ORMSupportClasses;

namespace BusinessTier
{
    public class PeopleFactory : Dal.FactoryClasses.PersonalEntityFactory
    {
        /// <summary>CTor</summary>
        public PeopleFactory() : base()
        {
        }

        /// <summary>Creates a new, empty People object.</summary>
        /// <returns>A new, empty People object.</returns>
        public override IEntity2 Create()
        {
            IEntity2 toReturn = new People();
            return toReturn;
        }

        /// <summary>Creates a new People instance but uses a special constructor which will set the Fields object of the new
        /// IEntity2 instance to the passed in fields object. Implement this method to support multi-type in single table inheritance.</summary>
        /// <param name="fields">Populated IEntityFields2 object for the new IEntity2 to create</param>
        /// <returns>Fully created and populated (due to the IEntityFields2 object) IEntity2 object</returns>
        public override IEntity2 Create(IEntityFields2 fields)
        {
            IEntity2 toReturn = new People(fields);
            return toReturn;
        }

        /// <summary>Creates, using the generated EntityFieldsFactory, the IEntityFields2 object for the entity to create. This method is used by internal code to create the fields object to store fetched data.</summary>
        /// <returns>Empty IEntityFields2 object.</returns>
        public override IEntityFields2 CreateFields()
        {
            return EntityFieldsFactory.CreateEntityFieldsObject(EntityType.People);
        }

        /// <summary>returns the name of the entity this factory is for, e.g. "EmployeeEntity"</summary>
        public override string ForEntityName
        {
            get { return "People"; }
        }
    }
}

People class:


using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Reflection;
using Dal.DatabaseSpecific;
using Dal.EntityClasses;
using Dal.HelperClasses;
using SD.LLBLGen.Pro.ORMSupportClasses;

namespace BusinessTier.Contacts
{
    public class People : PersonalEntity
    {
        public People(IEntityFields2 personId)
            : base(personId)
        {
        }

        public People(Int32 personId)
        {
            Id = personId;
            using (DataAccessAdapter adapter = new DataAccessAdapter(true))
            {
                adapter.FetchEntity(this);
            }
        }

        public People() : base()
        {
        }

    
        public string AddressString
        {
            get
            {
                string addressString = "";

                string[] address = Address;
                foreach (string addrLine in address)
                {
                    string addrLineEx = addrLine.Trim();
                    if (!addrLineEx.EndsWith(","))
                    {
                        addrLineEx += ",";
                    }
                    addressString += addrLineEx + "\n";
                }
                
                addressString = addressString.Trim();
                
                //Remove the final trailing comma...
                if(addressString.EndsWith(","))
                {
                    addressString = addressString.Substring(0, addressString.Length-1);
                }

                return addressString;
            }
        }


        /// <summary>Creates a new instance of the factory related to this entity</summary>
        protected override IEntityFactory2 CreateEntityFactory()
        {
            return new PeopleFactory();
        } 

    }
}

Thanks,

Shane

jmeckley
User
Posts: 403
Joined: 05-Jul-2006
# Posted on: 05-Jan-2007 15:40:00   

to clarify: 1.)are you adding the custom code region comments along with the custom code. -OR- 2.)are you placing your customer code within predefined custom code comments.

if option 2 then your code should not be overwritten. however, if option 1 then yes, your code will be removed when the DAL is refeshed, because the template your using doesn't know about to save that section. the custom code comments must come from the template to preserve your code.

ShaneN
User
Posts: 3
Joined: 04-Jan-2007
# Posted on: 05-Jan-2007 16:02:01   

Hi Jason,

Thanks for the response.

Just to clarify we're adding both the comment regions and the custom code (option 1). We're just starting to use LLBLGen so we just tried the suck-it-and-see approach to see if it worked, which it clearly didn't.

We're assuming that inheriting from the Entity classes isn't too out of the ordinary and that there's a relatively simple way of doing this that we're just not aware of.

Any advice is much appreciated.

Walaa avatar
Walaa
Support Team
Posts: 14983
Joined: 21-Aug-2005
# Posted on: 05-Jan-2007 16:04:54   

Answer for Q2:

the question is how do we keep our changes when we re-generate the Dal code (which we obviously need to do when adding new entities and modifiying existing ones)? We've tried using user comment regions to no avail. Or is there an alternate approach you'd recommend?

If you don't want to use pre-existing user code regions, then you might want to use .NET 2.0 partial classes (you can use new code files to extend existing classes)

Another option is to use Include templates.

Please refer to LLBLGen Pro manual: Using the generated code -> Adding your own code to the generated classes

jmeckley
User
Posts: 403
Joined: 05-Jul-2006
# Posted on: 05-Jan-2007 16:08:12   

the custom code regions have to be defined before you start coding (defined in the template). If they are not, then the code will be removed the next time you re-gen the objects.

you could try extending the factories in a seperate file. this would not be effected when refreshing the DAL. In your BL and PL you would then call your extended factory(s) instead of the base factory.

Walaa avatar
Walaa
Support Team
Posts: 14983
Joined: 21-Aug-2005
# Posted on: 05-Jan-2007 16:17:52   

Just to repeat it in other words. You should use User Code regions that already exists, you should not try to define new code regions (even if they have the same name). So either write your code within defined user code regions or don't. But if you try to copy the user code regions in another place , it will not work.

ShaneN
User
Posts: 3
Joined: 04-Jan-2007
# Posted on: 05-Jan-2007 17:00:44   

Hi guys,

Thanks for the responses.

Now that you've pointed it out it's clear that trying to shoehorn our code customisations into any old code section isn't going to work.

Jason, just to clarify, our Factory classes are in separate files from the generated code files and it's the generated EntityType enum and the generated EntityFieldsFactory class that we're adding our modifications to.

Below is example of what we were trying to do:


public static IEntityFields2 CreateEntityFieldsObject(EntityType relatedEntityType)
{
    IEntityFields2 fieldsToReturn=null;
    IInheritanceInfoProvider inheritanceProvider = InheritanceInfoProviderSingleton.GetInstance();
    IFieldInfoProvider fieldProvider = FieldInfoProviderSingleton.GetInstance();
    switch(relatedEntityType)
    {
        // The following 3 lines are customisations
        // __LLBLGENPRO_USER_CODE_REGION_START
        case Dal.EntityType.People:
        // __LLBLGENPRO_USER_CODE_REGION_END
        case Dal.EntityType.PersonalEntity:
            fieldsToReturn = new EntityFields2((int)PersonalFieldIndex.AmountOfFields, inheritanceProvider, fieldProvider.GetFieldIndexes("PersonalEntity"));
            CreatePersonalEntityFields(ref fieldsToReturn);
            break;
            ...
    }

    return fieldsToReturn;
}

The reason for adding the customisations was that we thought we needed to use a new EntityType and entity name, that was specific to our domain class (People) in the PeopleFactory class. Thinking about this again I've just tried removing these from the PeopleFactory, so the factory uses the EntityType.PersonalEntity and entity name 'PersonalEntity' from the base PersonalEntityFactory class. From my limited tests this works and would obviously mean that we wouldn't need to make any customisations to the generated code but can you guys see any potential problems?

Walaa, we did consider using partial classes but we'd prefer to build the business model in a separate library and our situation is complicated by having multiple database schemas (we'd prefer to keep the data access layers for the different db schemas in seperate projects but combine them in the business model). Partial classes are still an option, though not our preferred one.

Like we've said we're new to LLBLGen and we know what like to do but we're still feeling are way around trying to find out how to do it, so your help is very appreciated.

Thanks, Shane