Discriminator Column

Posts   
 
    
tprohas
User
Posts: 257
Joined: 23-Mar-2004
# Posted on: 19-Oct-2005 02:56:51   

I have an entity called TireEntity, this tire can be placed either in the front or the rear. Now for the discriminator column I have four possible values, 'F' (Front), 'R' (Rear), 'S' (a set or pair), then lastly I have 'B' (Both). Now the problem I'm having is that I want the logic when selecting the fronts and rear to also select the 'B'/Boths as well. The reason is that some tires are marked as being specifically for the font or rear, but then there are other tires that are marked as both as they can be used on either the front or rear. Is this possible using a discriminator column?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 19-Oct-2005 09:41:37   

No, as you then have a type which is a subtype of both and multiple-inheritance isn't supported. So you have to model 'B' as a sibling of F and R.

To fetch F and B together, you could produce a filter which filters on F (type filter) and B. See the new filtering/sorting section how to produce a type filter. (entityname.GetEntityTypeFilter() )

Frans Bouma | Lead developer LLBLGen Pro
tprohas
User
Posts: 257
Joined: 23-Mar-2004
# Posted on: 27-Oct-2005 19:28:25   

OK, I'm now trying to figure this out and so far its not working. I have a Tire entity that I then created FrontTire and RearTire from. In the designer the window asks for the Tire discriminator value and I used 'B', I then used 'F' for the FrontTire and 'R' for the RearTire. Was this the correct way to doing this?

Here is the code that I'm using:

public EntityCollection GetFrontTires(string styleCode)
{
    EntityCollection frontTires = new EntityCollection(new FrontTireEntityFactory());
    
    RelationPredicateBucket filter = new RelationPredicateBucket();
    filter.PredicateExpression.AddWithOr(TireFields.FrontOrRear == "B");
    
    DataAccessAdapter adapter = new DataAccessAdapter();
    adapter.FetchEntityCollection(frontTires, filter);

    return frontTires;
}

This code is producing a query that is very close to what I want.

exec sp_executesql N'SELECT [WS2].[dbo].[Tire].[TireID] AS [F0], [WS2].[dbo].[Tire].[ProductVersionID] AS [F1], [WS2].[dbo].[Tire].[BeadType] AS [F2], [WS2].[dbo].[Tire].[FrontOrRear] AS [F3], [WS2].[dbo].[Tire].[TireMountType] AS [F4], [WS2].[dbo].[Tire].[Width] AS [F5], [WS2].[dbo].[Tire].[WheelSize] AS [F6]
FROM [WS2].[dbo].[Tire]
WHERE ( ( [WS2].[dbo].[Tire].[FrontOrRear] = @FrontOrRear1)
AND ( [WS2].[dbo].[Tire].[FrontOrRear] = @FrontOrRear2))'
, N'@FrontOrRear1 char(1),@FrontOrRear2 char(1)'
, @FrontOrRear1 = 'B', @FrontOrRear2 = 'F'

The problem with this query is that its using AND between the two FrontOrRear predicates. I want it to use OR so that both F and B values are queried.

I did try using the GetEntityTypeFilter() like this.

filter.PredicateExpression.Add(FrontTireEntity.GetEntityTypeFilter());

The result was that the query was looking for FrontOrRear = 'F' twice which isn't helping. What should I do now?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 28-Oct-2005 10:17:02   

The SQL produced seems to be wrong. WIll look into it.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 28-Oct-2005 11:55:25   

This is a bug in the llblgen pro runtime code. A small explanation: hierarchy:

A <- B A <- C <- D A <- C <- E

You create an entity collection for C's. (adapter or selfservicing, doesn't matter). Then you want to fetch all C's. In the case of a TargetPerEntity, a typefilter for C has to be added. The code does this automatically for you, as this shouldn't be necessary, after all you created a collection of C's. This filter is added with AND. This works, because multiple tables are involved.

In the case of TargetPerEntityHierarchy it should do: AND DiscriminatorColumn IN (C.DiscriminatorValue, D.DiscriminatorValue, E.DiscriminatorValue). Apparently it produces an optimization, for 1 value: AND field IN (value) is very slow on SqlServer, so it produces: AND field = value apparently, which of course should be: OR field = value.

I.o.w.: bug, it seems, will be fixed.

(still investigating)

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 28-Oct-2005 12:08:16   

Btw, you fetch a FrontTire collection, but a tire isn't a fronttire (type wise). So you want to fetch fronttires, and you then can't fetch a supertype into that collection, as it's not a fronttire.

You can achieve what you want though by fetching a tire collection, and specifying a filter which says: NOT a reartire. You'll get a query which says something like: WHERE FrontOrRear != 'R' -- filter which you added and which says no rear tire AND FrontOrRear IN ('B', 'R', 'F') -- filter added by the code which makes sure the particular type and all its subtypes are fetched.

Though I think what you should do is define 3 subtypes: (with an abstract Tire type): FrontTire, RearTire and GenericTire. Because now a FrontTire is a subtype of a tire which can be a reartire as well, which is odd because it suggests FrontTire LOSES a specification through the inheritance, which is of course not correct: it inherits the specifications of the supertype, which says: can be rear OR front.

To specify NOT a reartire do:


public EntityCollection GetFrontTires(string styleCode)
{
    EntityCollection frontTires = new EntityCollection(new TireEntityFactory());
    
    RelationPredicateBucket filter = new RelationPredicateBucket();
    filter.PredicateExpression.Add(RearTireEntity.GetEntityTypeFilter(true));
    
    DataAccessAdapter adapter = new DataAccessAdapter();
    adapter.FetchEntityCollection(frontTires, filter);

    return frontTires;
}

I'll rethink the sematics of my code. It could still be a bug, but not in this situation.

(edit): not a bug, the query filters produced by llblgen pro is correct: it produces discriminator filters for the actual type to fetch AND all its subtypes. If there's just 1 value, there are no subtypes, so it works ok, and if there are subtypes, it will become an IN filter, which is also correct.

Frans Bouma | Lead developer LLBLGen Pro