Refresh of database overwrites underlying .NET types

Posts   
 
    
JSobell
User
Posts: 145
Joined: 07-Jan-2006
# Posted on: 07-Dec-2015 08:18:49   

I'm using enums for most Status values in the database, but every time I refresh the database it stonks over them with the original Uint62/Int32/whatever. Is there a way to define that attributes called OrderStatusId should be auto-mapped to eOrderStatus?

Cheers, Jason

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39612
Joined: 17-Aug-2003
# Posted on: 07-Dec-2015 14:29:00   

I can't reproduce it. I use enums using the type imports feature, not sure how you use enums, through type converters?

Which llblgen pro version (build date as well it's in the title bar) are you using?

Frans Bouma | Lead developer LLBLGen Pro
JSobell
User
Posts: 145
Joined: 07-Jan-2006
# Posted on: 08-Dec-2015 01:54:20   

Otis wrote:

Which llblgen pro version (build date as well it's in the title bar) are you using?

Hi Otis, I'm now using 20 Nov 2015, but the cause is a bit more fundamental.

If you choose a field that has a FK relationship it re-adopts the type of the PK on the associated table when you reload it, even though the XML remains unchanged. If you remember to go to the FK table and change it's PK to the same Enum type then the problem goes away.

Why have a table related to this one as a FK at all? Well we do this because when we generate reports or output we want the name associated with the Enum, rather than the numeric value, and we can go through deleting all of the relationships, but they are useful for data consistency. We generate all the Enums from these tables using T4 templates (and also the .typeimports and even javascript files) so we want to retain them.

Perhaps the designer could either generate a warning when the FK type is not the same as the PK on any relationship, or ask the user if they would also like to associate the primary key with this type.

Also, my original question was whether there is any way to auto-map the datatype for a field based on its name. This would prevent this problem, as the PK would also acquire the same enum type so long as you adopt a convention for non-default typed fields. For example, on the 'Custom Type Shortcuts' could there be a way of associating a type with a column name, regex, or list of names, so that during generation of the Entity it automatically associated that type?

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 08-Dec-2015 07:02:06   

JSobell wrote:

Also, my original question was whether there is any way to auto-map the datatype for a field based on its name. This would prevent this problem, as the PK would also acquire the same enum type so long as you adopt a convention for non-default typed fields. For example, on the 'Custom Type Shortcuts' could there be a way of associating a type with a column name, regex, or list of names, so that during generation of the Entity it automatically associated that type?

There are auto type-mappings (type converters definitions) but they are based on type description (datatype, length, etc). If you want to discriminate by other things, you could write a plugin and bind it to designer events. See Implementing a plug-in for more information.

David Elizondo | LLBLGen Support Team
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39612
Joined: 17-Aug-2003
# Posted on: 08-Dec-2015 10:02:28   

JSobell wrote:

Otis wrote:

Which llblgen pro version (build date as well it's in the title bar) are you using?

Hi Otis, I'm now using 20 Nov 2015, but the cause is a bit more fundamental.

If you choose a field that has a FK relationship it re-adopts the type of the PK on the associated table when you reload it, even though the XML remains unchanged. If you remember to go to the FK table and change it's PK to the same Enum type then the problem goes away.

Why have a table related to this one as a FK at all? Well we do this because when we generate reports or output we want the name associated with the Enum, rather than the numeric value, and we can go through deleting all of the relationships, but they are useful for data consistency. We generate all the Enums from these tables using T4 templates (and also the .typeimports and even javascript files) so we want to retain them.

Perhaps the designer could either generate a warning when the FK type is not the same as the PK on any relationship, or ask the user if they would also like to associate the primary key with this type.

Also, my original question was whether there is any way to auto-map the datatype for a field based on its name. This would prevent this problem, as the PK would also acquire the same enum type so long as you adopt a convention for non-default typed fields. For example, on the 'Custom Type Shortcuts' could there be a way of associating a type with a column name, regex, or list of names, so that during generation of the Entity it automatically associated that type?

Am I correct that the following represents your situation: you have an entity Product and an entity ProductType. Product has a m:1 relationship with ProductType. ProductType has a PK ID (int) and a Description field. Product's FK field ProductTypeID is of type ProductType (and not int) which is an enum, and represents the values in the table ProductType is mapped on.

(so Product.ProductTypeID is of a different type than ProductType.ID ?)

If ProductType is a 2 field entity for lookups only (as it has no real value other than to produce descriptions), is it really necessary to have the FK field set as an enum and have the relationship? the thing is that the enums are generated from the DB rows, so you can effectively use the lookups through the enums and don't need the lookup entities. I mention this as fk-pk fields not having the same types can be problematic.

Frans Bouma | Lead developer LLBLGen Pro
JSobell
User
Posts: 145
Joined: 07-Jan-2006
# Posted on: 08-Dec-2015 11:17:09   

Otis wrote:

Am I correct that the following represents your situation: you have an entity Product and an entity ProductType. Product has a m:1 relationship with ProductType. ProductType has a PK ID (int) and a Description field. Product's FK field ProductTypeID is of type ProductType (and not int) which is an enum, and represents the values in the table ProductType is mapped on.

(so Product.ProductTypeID is of a different type than ProductType.ID ?)

If ProductType is a 2 field entity for lookups only (as it has no real value other than to produce descriptions), is it really necessary to have the FK field set as an enum and have the relationship? the thing is that the enums are generated from the DB rows, so you can effectively use the lookups through the enums and don't need the lookup entities. I mention this as fk-pk fields not having the same types can be problematic.

Hi Frans (I must stop calling you Otis!), Almost. Firstly, the database field type is the same in both cases, be it int, ubyte or long, so the lookup entities as attached fields are sometime redundant, but as separate entities they are useful so they are retained. Overall, it's important top keep the DB relationship as it provides referential integrity, self-documentation, and descriptive reporting. In LLBLGen it's less important unless you want to retain the ability to access other fields such as Descriptions against the associated status of an object, so it's far from useless to retain the association, but it's obviously not an efficient thing to filter on the Name of the associated status entity.

So underlying the system, the type of Enum and type Int are essentially interchangeable and it's common to have code saying things like .Where(item => item.StatusId == (int)eStatus.Closed ) in preference to .Where(item => item.StatusId == 3)

The beauty of the LLBLGen approach is being able to say .Where(item => item.StatusId == eStatus.Closed ) with auto-completion because item.StatusId is an Enum type. (and of course I can still get to item.Status.Description too if the related Entity is included)

So overall, we should ensure both FK and PK are represented by the same type (int or enum), and I'm suggesting that the designer warn us when we have LLBLGen relationships defined with different types. At the moment the designer stonks over the FK type with the PK type with no warning or message, and even though the underlying XML still has the user's chosen type, that's not reflected on screen. If the warning said "Different types used in relationship X - (Company.Enums.eMyThing[FK] -> System.Integer[PK]) - [PK] has priority" then I would realise that I forgot to set the PK on tblStatusTypes to also be Company.Enums.eMyThing.

Does any of this make sense?

Cheers, Jason

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39612
Joined: 17-Aug-2003
# Posted on: 09-Dec-2015 11:18:02   

Ah yes, makes sense.

I was first thinking about fine-tuning the syncing of the types, but that's not going to work as when the PK side is saved, the value is synced with the FK side entity and as the PK field is an int, the FK field becomes an int too and when reading the value after that through the property might work, it also might lead to an invalid cast exception, so that's not going to be reliable.

I'll look into the warning you suggest. It should be there already but perhaps it doesn't trigger as it assumes int and enum have implicit conversions.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39612
Joined: 17-Aug-2003
# Posted on: 09-Dec-2015 16:18:21   

When the types mismatch (Int PK, Enum FK) I get a validation error, which is correct:

Message type: Error Message text: The relationship 'ProductEnumTest.Category - Category.ProductEnumTest (m:1)' has for the primary key field 'CategoryId' the foreign key field 'ProductEnumTest.CategoryId (FK)' assigned, which has a different value for 'field type' (CategoryType (EnumTypes.CategoryType)) set than the primary key field (int (System.Int32)). Source: ProductEnumTest.Category - Category.ProductEnumTest (m:1)

So I set the PK field Category.CategoryID also to the enum type. Error is then gone, as it should.

When I refresh, the pk & fk keep their enum type however. Nothing is reset to int. So I'm a bit confused how to reproduce your situation...

Frans Bouma | Lead developer LLBLGen Pro
JSobell
User
Posts: 145
Joined: 07-Jan-2006
# Posted on: 11-Dec-2015 03:45:01   

Otis wrote:

When I refresh, the pk & fk keep their enum type however. Nothing is reset to int. So I'm a bit confused how to reproduce your situation...

So was I when I just tried reproducing it. It appears to be a designer related error, and can be reproduced this way:

Load definition with PK=Int32, FK=Int32 Change FK field to eWhatever Save the file. Close the designer (it strangely prompts you to save your changes again) Reopen the file, and the field has returned to an integer.

As I was updating about 30 fields to Enums, I didn't validate or generate entities until I saved my changes, and had subsequently closed and reopened the project. So if a project is saved with a PK/FK mismatch, it reloads and automatically reverts to the PK type.

Cheers, Jason

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39612
Joined: 17-Aug-2003
# Posted on: 11-Dec-2015 09:47:41   

ah, save load, that's indeed not what I tested. Strange issue, we'll look into it!

Frans Bouma | Lead developer LLBLGen Pro
Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 11-Dec-2015 09:52:12   

I got your point about the designer reverting the changes.

On another note: you want to set an enum type for a PK. This will make a database table a representation of an enum, I'm not sure if this is the best approach. DB Tables should be updatable, even for Lookups, enums are hardcoded. Do you really want to maintain the lookup in 2 places (database & code)?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39612
Joined: 17-Aug-2003
# Posted on: 11-Dec-2015 13:42:19   

Reproduced the issue. Looking into it.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39612
Joined: 17-Aug-2003
# Posted on: 11-Dec-2015 14:34:56   

Fixed in next build (December 11th)

Frans Bouma | Lead developer LLBLGen Pro