TypeConverter, Inheritance and Discriminator

Posts   
 
    
ChBaeumer
User
Posts: 175
Joined: 23-Oct-2003
# Posted on: 16-Oct-2008 10:27:06   

Hi Otis,

it seems that if I use a TypeConverter on a discriminator field a ORMInheritanceInfoException is thrown.

The problem here is that the type converter has not kicked in and the type of the field is not correct.

In my case I move from GUIDs to char(36) and have a converter for this. But the inheritance info is registered with GUIDS whereas during a fetch the database value is a string.

Christoph

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 16-Oct-2008 11:47:29   

But the inheritance info is registered with GUIDS whereas during a fetch the database value is a string.

How come the inheritance info is registered with GUIDS whereas during a fetch the database value is a string?

ChBaeumer
User
Posts: 175
Joined: 23-Oct-2003
# Posted on: 16-Oct-2008 11:51:41   

How it comes?

By constructing the inheritance hierachy you have to specify a discriminator field. This field is on the db a char(36) field but is converted to a system type of GUID.

And the system type is used to check the inheritance.

You already looked at my type converter wink You can use it to check this.

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 16-Oct-2008 12:08:30   

it seems that if I use a TypeConverter on a discriminator field a ORMInheritanceInfoException is thrown

Would you please post a stack trace, and the runtime library version used?

You already looked at my type converter You can use it to check this.

Where can I find it? Would you please attach it?

ChBaeumer
User
Posts: 175
Joined: 23-Oct-2003
# Posted on: 16-Oct-2008 12:21:41   

The TypeConverter thread:

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

StackTrace is a problem. I included the source code of the ORM support classes into my solution and compiled against it:

class InheritanceInfoProviderBase method private IEntityFactoryCore GetEntityFactoryTargetPerEntityHierarchy( string entityName, object[] values ) lineno 1263

Looking at the code the behaviour is clear to me:

The EntityInfo is registered with the system type (here Guid). In the method above the entityfactory is searched by the raw values from the database (in my case string). At this point it is not possible to get access to the field info where the typeconverter is stored in order to convert the db type to the system type. This is done after the correct factory is found.

Christoph

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 16-Oct-2008 14:34:43   

You're correct on the behavior, the field data is converted right before it's inserted into the fields object, thus when the factory is already known.

The question then is of course, will I change the code. It's a rather simple change, but any change can have big impact, as it's at the very core of the o/r mapper's object fetch pipeline: right after the datareader has read the rows, for all persistenceinfos passed into the routine, each value has to be converted, if required, then the stuff is processed further.

There's also the problem where the row reader has to know if a value was converted: some type converters could be used to produce non-null values for null values for non-nullable database fields and vice versa. Converting the stuff outside the row reader requires that the rowreader gets this info, but the signature doesn't allow that (and it's a protected virtual routine, as it is overriden by some customers for special pre-processing). Furthermore, converting the data outside the rowreader would make the parameter for the persistence info useless.

So, the change could be made, but it breaks code or has a high impact, something which we'll not do in the middle of a release. (i.o.w.: I could file a change request for v3, but not for this version).

I pressume your code runs on oracle and you decided to use guids because your app also uses sqlserver? Otherwise why use this approach, if I may ask?

It's not that big of an impact for you really, as discriminator values aren't used in your code (they're hidden away from you) so if the field is a guid or not doesn't really matter much.

Frans Bouma | Lead developer LLBLGen Pro
ChBaeumer
User
Posts: 175
Joined: 23-Oct-2003
# Posted on: 16-Oct-2008 16:35:14   

Hi Otis,

I started years before with the sql server and decided to use Guids as PK for all my entities.

Now I want to use other db vendors as well hence the change.

I have a special case in this application (you made this change for me flushed ) The discriminator is also a foreign key to another entity. So, in my case it will be a breaking change.

What I have done as work around:

I modified the TypeConverter to accept strings as well and register the disriminator field with the db type (as string) instead of the system type (as guid). So far it works.

The only place where I would change the code would be to enhance EntityInfo with a type converter for the discriminator, change the inheritanceInfoProviderDerived.template and then check in the GetEntityFactoryTargetPerEntityHierarchy method if for the discriminator a type converter is registered.

That would'nt be so much changes. But it's up to you.

Perhaps you should at least note this in your beautiful documentation.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 16-Oct-2008 17:56:47   

ChBaeumer wrote:

Hi Otis, I started years before with the sql server and decided to use Guids as PK for all my entities. Now I want to use other db vendors as well hence the change.

I have a special case in this application (you made this change for me flushed ) The discriminator is also a foreign key to another entity. So, in my case it will be a breaking change.

That's why you shouldn't use discriminator fields as FK fields: it allows you to change types inside the data through code.

What I have done as work around:

I modified the TypeConverter to accept strings as well and register the disriminator field with the db type (as string) instead of the system type (as guid). So far it works.

That should do the trick indeed. simple_smile

The only place where I would change the code would be to enhance EntityInfo with a type converter for the discriminator, change the inheritanceInfoProviderDerived.template and then check in the GetEntityFactoryTargetPerEntityHierarchy method if for the discriminator a type converter is registered.

That would'nt be so much changes. But it's up to you.

Type converters can't be in EntityInfo, as they're db specific, so they're in the mapping meta data, not in the entity meta-data. I've logged a change for v3 to do typeconverter runs right after the row has been fetched from the datareader and from then on proceed as-is, so no type converter usage after that.

Perhaps you should at least note this in your beautiful documentation.

Will do simple_smile

Frans Bouma | Lead developer LLBLGen Pro
ChBaeumer
User
Posts: 175
Joined: 23-Oct-2003
# Posted on: 16-Oct-2008 20:21:00   

That's why you shouldn't use discriminator fields as FK fields: it allows you to change types inside the data through code.

The reason for this is that I use a meta model, too, which is saved in the database as well.

I didnt't find another solution for this.

I will stick to my trick. I just have to remember that I'll have to change the InheritanceInfoProvider simple_smile and wait for the next version...

TomDog
User
Posts: 618
Joined: 25-Oct-2005
# Posted on: 28-Sep-2009 22:33:48   

Otis wrote:

I've logged a change for v3 to do typeconverter runs right after the row has been fetched from the datareader and from then on proceed as-is, so no type converter usage after that.

I've hit this problem as well - we have a situation where the Discriminator Column is a Int16 in sql server but comes through as a Int32 (from NUMBER(5,0) when connected to Oracle.

Our Oracle schema is generated from our SQL server schema by a tool which bumps up the precision so we have type converters on all the numeric fields on Oracle which works OK except for discriminator columns, so we have to make a special case for conversion of the Discriminator Columns.

Can't wait for V3!

Jeremy Thomas
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 29-Sep-2009 10:22:14   

Unfortunately I can't make the change for v2.6, as it's a breaking change. The change therefore is postponed till v3.

The thing you might want to look into is that the precision on oracle for discriminator fields is lowered to 4, so the type is a short, not an int. But I'm not sure if that's sufficient for your usage of oracle of course... (and I'm sure you've already looked into that).

Frans Bouma | Lead developer LLBLGen Pro
TomDog
User
Posts: 618
Joined: 25-Oct-2005
# Posted on: 29-Sep-2009 12:12:20   

Otis wrote:

The thing you might want to look into is that the precision on oracle for discriminator fields is lowered to 4, so the type is a short, not an int. But I'm not sure if that's sufficient for your usage of oracle of course... (and I'm sure you've already looked into that).

Yeah what I was trying to say is that our conversion tool converts smallints to NUMBER(5,0) and as a manual step afterwards we change the two discriminator fields to NUMBER(4,0) - just be nice to not have to do that.

I guess with V3 both SQL server and Oracle will able to be generated by the designer so we can skip the whole conversion process completely.smile

Jeremy Thomas
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 20-May-2010 12:25:39   

Looking into this problem, it is possible to change this in the runtime, however it requires more changes than a simple swap of 2 calls, as the row has to be pre-processed before it's read. We decided to postpone this change to a future 3.x version when we revisit the runtime.

Frans Bouma | Lead developer LLBLGen Pro