Getting Sub Type based off of Discrimator Field

Posts   
 
    
Posts: 112
Joined: 09-Aug-2004
# Posted on: 14-Apr-2008 21:17:14   

Taking the example on the home page,

Is it possible to use the Discriminator Field to get an instance of the Sub Type?

I'd like to be able to write code like the following



int discrimatorField = int.Parse(ddlCarType.SelectedValue); //7

CompanyCarEntity car = CompantCarEntity.GetSubType(discrimatorField);

car.GetType().Name; //JapaneseFamilyCarEntity


Thanks.

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 15-Apr-2008 05:46:47   

Yes. You could do that this way:

int discrimatorField = int.Parse(ddlCarType.SelectedValue); //7

CompanyCarEntity car = CompantCarEntity.FetchPolymorphic(null, discrimatorField, null);

car.GetType().Name; //JapaneseFamilyCarEntity

Ref: LLBLGenPro Help - Using generated code - SelfServicing - Using the entity classes - Polymorphic fetches

David Elizondo | LLBLGen Support Team
Posts: 112
Joined: 09-Aug-2004
# Posted on: 15-Apr-2008 19:17:33   

I am actually using the Adapter model, sorry I should have been more specific. I am looking at the same help code for Adapter, and it doesn't appear that you can pass in the value as an arugment. It looks like FetchNewEntity only takes a IRelationPredicateBucket. Would I specify the discrimnator in there?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39903
Joined: 17-Aug-2003
# Posted on: 16-Apr-2008 14:35:24   

You don't have to, the fetch routine figures out the type itself: the filter matches 1 entity and the data is loaded into the right type.

Frans Bouma | Lead developer LLBLGen Pro
Posts: 112
Joined: 09-Aug-2004
# Posted on: 16-Apr-2008 15:39:41   

Ahh interesting, that works. Is there a reason that you have to use the Adapter for new Entities? I'd imagine the generated code could be a simple switch for each type/

Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 16-Apr-2008 18:01:51   

Is there a reason that you have to use the Adapter for new Entities? I'd imagine the generated code could be a simple switch for each type/

I didn't quite understand your question.

Posts: 112
Joined: 09-Aug-2004
# Posted on: 16-Apr-2008 20:26:58   

So when I create new Entities via Polymorphism, I don't understand the need for the adapter. I'd imagine that a method with a switch would be enough, for example



//this method could exist on the CompanyCar object.
public static CompanyCar GetSubType(int discriminator) {

    switch (i) {
        case 1 : 
            return new CompanyCar();
            break;
        case 2 :
            return new FamilyCar();
            break;
        case 3 :
            return new SportsCar();
            break;
        case 4 :
            return new ItalianSportsCar();
            break;

        ...
        ...
        ...

    } 
}


Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 17-Apr-2008 10:46:57   

If you know the discriminator value then you can create an en entity of the subType corresponding to the disc. value.

The adapter and polymorphisim is used when you are fetching an entity without knowing it's subType or its discriminating value, for example by its PK.

Similar question was asked here: http://www.llblgen.com/TinyForum/Messages.aspx?ThreadID=4475

Posts: 112
Joined: 09-Aug-2004
# Posted on: 17-Apr-2008 17:16:30   

I guess this is where I am confused...

Walaa wrote:

If you know the discriminator value then you can create an en entity of the subType corresponding to the disc. value.

My interface is set up such that the user is creating a new instance of a car. There is a drop down specifying the car type. The discriminator value is the value of the drop down. So I know the number, but I don't really know the type since I don't want to have my code store a mapping of discriminator values and types. I really don't care what type it is, I'd just like to pass the selected value on.

It sounds like in the other thread, Frans mentioned this functionality isn't offered from the code publicly to avoid the use of hard coded discriminator values. The end solution also made use of ForceCurrentValueWrite which is marked as Do Not Use.

Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 18-Apr-2008 10:51:12   

Instead of using the discriminator values in the dropdownList, why don't you use the entityType enum values?

Posts: 112
Joined: 09-Aug-2004
# Posted on: 18-Apr-2008 15:08:03   

Those items from the drop down list are coming from a related table which stores the type. So There would be a table

1 CompanyCar 2 FamilyCar 3 SportsCar ... ...

So how would I bind to the entity type enum value for the related type?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39903
Joined: 17-Aug-2003
# Posted on: 19-Apr-2008 12:06:34   

When you create an entity instance object (e.g. new FamilyCar(); ) you can't switch the discriminator column anymore after that, because that would imply changing the type of the whole object, which isn't possible.

So you need a factory to create the instances based on the discriminator value. E.g. in your example, if the value is '2', the entity object to create is a FamilyCarEntity instance. However, you can't do: - create a companycar entity instance, - set the discriminatorcolumn - and expect it to be a familycarentity instance simple_smile Because we're working with objects which have a fixed type.

So your dropdown's selection controls what entity is created AFTER selection. It doesn't control the entity which is already created. So there's no binding from combo to discriminator field, as it's not possible to set that field afterwards. (as I've explained above).

So, if you know the discriminator value, and you want to create the entity instance belonging to that discriminator value, you've to obtain the right factory for that discriminator column. You can use the same code path as the fetch logic does: use the root entity type's factory and call GetEntityFactory() on it by passing in an array of values and '0' as the index. the array of values is at least as wide as the # of fields in the root entity and place the discriminator value at the index of the discriminator field.

So say your root type CompanyCar has its discriminator field at index 3, and has 4 fields in total, you pass: new object[] { null, null, 3, null}; and you'll get a factory back. You then call that factory's Create method and you'll get the entity of the right type. You can also use David's trick mentioned earlier or use a switch/case clause on your own.

Frans Bouma | Lead developer LLBLGen Pro
Posts: 112
Joined: 09-Aug-2004
# Posted on: 21-Apr-2008 16:24:08   

Thanks for all of the responses.

I think I will stick with David's solution for the time being. I like the use of the entity factory, but I think passing in an array of index based values is a bad idea for long term code maintenance.

I understand not being able to change the type based on the discriminator field after the object is created. The drop down is letting the user select the type of car, when they go to save, I am creating the appropriate type based off of their selection. I thought there would be a more direct way of creating the type from the discriminator field since there is a clear relationship between the objects.

Hmm, Maybe this would be a good plug in for me to write. Basically generate that switch statement I was mentioning earlier.