Fields MaxLength issue

Posts   
 
    
kpeulic
User
Posts: 8
Joined: 29-Nov-2007
# Posted on: 08-Sep-2016 16:10:13   

Hi,

I'm using LLBLGen 4.2 Final version.

In PostgreSQL database, I have "citex"fields and when I generated entities, max. length for these fields is 1073741824.

I manually changed max. length from 1073741824 to 50 in the LLBLGen project.


<EntityDefinition Name="Client" ObjectID="ef1165f2-5928-4029-b837-670fe508f0c7">
        <Fields>
          <Field Name="FirstName" Type="string" MaxLength="50" />
          <Field Name="Id" Type="guid" IsPrimaryKey="true" />
          <Field Name="LastName" Type="string" MaxLength="50" />
        </Fields>


<Table Name="CmsClient">
                  <PkConstraintName Name="Client_ID" />
                  <Fields>
                    <Field Name="Id" Ordinal="1" IsPrimaryKey="true" DbType="28" />
                    <Field Name="FirstName" Ordinal="4" DbType="32" Length="1073741824" />
                    <Field Name="LastName" Ordinal="5" DbType="32" Length="1073741824" />
                  </Fields>
                </Table>

When I generated source code, max. length for that field is again 1073741824 instead of 50 as I want.


this.AddElementFieldInfo("ClientEntity", "FirstName", typeof(System.String), false, false, false, false,  (int)ClientFieldIndex.FirstName, 1073741824, 0, 0);


 txtFirstName.MaxLength = ClientFields.FirstName.MaxLength;

Can you please check is this a bug or I'm doing something wrong?

Thanks, Kruno

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 08-Sep-2016 16:50:31   

Please get the latest build which has support for Citex types. Do you use the latest build?

Addition Drivers 4.2 Drivers 4.2 09082016 09-Aug-2016 PostgreSQL: Added support for citext type.

Frans Bouma | Lead developer LLBLGen Pro
kpeulic
User
Posts: 8
Joined: 29-Nov-2007
# Posted on: 08-Sep-2016 17:11:54   

Yes, I'm using latest build.

SD.LLBLGen.Pro.DBDrivers.PostgreSqlDBDriver.dll - 42.15.1218 LLBLGenPro.exe - 4.2.16.504

And in my PersistenceInfoProvider file I have "Citex" as sourcColumnDbType:


this.AddElementFieldMapping("ClientEntity", "FirstName", "FirstName", false, "Citext", 1073741824, 0, 0, false, "", null, typeof(System.String), 6);

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 08-Sep-2016 17:15:00   

What is the length of the fields in the database, could you give a DDL SQL create statement of the table you use ?

Frans Bouma | Lead developer LLBLGen Pro
kpeulic
User
Posts: 8
Joined: 29-Nov-2007
# Posted on: 08-Sep-2016 17:33:56   

Citex database type doesn't have specified length in the database. Here is the DDL SQL script:


CREATE TABLE "public"."CmsClient"
(
    "Id" uuid NOT NULL, 
    "ClientInformationId" uuid NULL, 
    "ClientNumber" int2 NULL, 
    "FirstName" citext NOT NULL, 
    "LastName" citext NOT NULL, 
    "Phone1" citext NULL, 
    "Phone2" citext NULL, 
    "Email1" citext NULL, 
    "Email2" citext NULL, 
    "Unsubscribe" bool NOT NULL, 
    "Birthday" timestamp NULL, 
    "Employer" citext NULL, 
    "PhoneType1Id" uuid NULL, 
    "PhoneType2Id" uuid NULL, 
    "RelationshipTypeId" uuid NULL 
);

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 08-Sep-2016 18:33:38   

From the dates you posted, it seems you have an older dlls. The latest as posted by Frans(Otis) was released in Aug. 2016

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 09-Sep-2016 07:32:06   

Yes, they're outdated, though I think the main issue is the length of the fields not being defined: it then simply picks 1GB (as there's no length defined, it assumes a clob)

If you change the length of the entity field manually, it gets resynced with the db field length after a refresh. In v4.2 this is controlled by the preference Length precision scale follow dblength precision scale. The value of that can be overruled per project in the project setting (under Database first development) with the same name. As the default is 'true', this is likely the cause you get the field resynced after a refresh. Change the project setting from 'default' to 'false' and the manually set field lengths shouldn't be overwritten.

You don't need to change the field lengths in the xml btw, you can do so in the entity editor. Better is of course to define a size/maxlength in the DB schema.

Frans Bouma | Lead developer LLBLGen Pro
kpeulic
User
Posts: 8
Joined: 29-Nov-2007
# Posted on: 09-Sep-2016 09:16:11   

I downloaded the latest build and after the installation, I can confirm that my previous version was up to date, since versions are the same:

LLBLGenPro.exe - 4.2.16.504 SD.LLBLGen.Pro.DBDrivers.PostgreSqlDBDriver.dll - 4.2.15.1218

Once again, in the PostgreSQL you cannot specify length on the "citex" fields - default length for "citex" fields is 1073741824 (1GB).

As I mentioned, I have manually changed my field length (in the entity editor, of course simple_smile ) and after the refresh, these lengths wasn't changed, they are the same as I specified in the entity editor. (property: Length precision scale follow dblength precision scale is set as default).

When I generated source-code, my manual changes (length in entity editor) are not generated in the source-code.


this.AddElementFieldInfo("ClientEntity", "FirstName", typeof(System.String), false, false, false, false,  (int)ClientFieldIndex.FirstName, 1073741824, 0, 0);
this.AddElementFieldInfo("ClientEntity", "LastName", typeof(System.String), false, false, false, false,  (int)ClientFieldIndex.LastName, 1073741824, 0, 0);

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 09-Sep-2016 13:54:15   

Ah, my mistake regarding the versions, indeed the file version wasn't updated in the assembly.

Anyway, the length emitted in the field info is the length of the mapped target field. In general these are kept the same as the target field and they're used for validation at runtime to make sure the value fits the target. It also only shows up when the database contains no lengths or the wrong lengths/size. It's in general not a problem: model first will have a db following the entity field, and db first will have an entity field following the db, hence we didn't change it since v2 (where the numbers were automatically kept in sync).

Looking at it, it might be good to change it in v5.1 as an option (default off), as manually changing the value suggests you'd like to use that length, not the target length. It also allows users to automatically use the built-in validation for the lengths/precision/scale values defined on the entity, not on the target DB which might differ.

For citext fields today in v4.2/5.0, this is a bit of a problem indeed, as they don't have a length defined in the database, so they're seen as 1GB, as the DB accepts 1GB per citext field.

So to help you further, in what context do you use the field lengths defined in the entity or want to use it? You use the length of the fields for validation in a UI system? llblgen pro can generate validation attributes (with the defined field length in the entity) easily in an general manner so you can define it once and it generates them using rules on all string fields. Additionally you could write a validator class and inject it into all entities using the built-in dependency injection to validate the lengths based on the attribute defined on the field.

You could also change the template, but that might be overkill. For the use case we can then advice you better what to do to get the real lengths usable in your application.

Frans Bouma | Lead developer LLBLGen Pro
kpeulic
User
Posts: 8
Joined: 29-Nov-2007
# Posted on: 09-Sep-2016 14:28:08   

Thanks for the response.

The most suitable solution for me will be to change the template.

Can you please point me in the right direction, what template to change in order to generate additional property on MyEntityFields.FieldName e.g. MyEntityFields.FieldName.ModelMaxLength which will contain maxLength value manually changed in entity editor? Also, what is the variable or object that I can use in the template to get this value ?

Regards

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 09-Sep-2016 15:05:54   

Entityclass.FieldName returns the value of the field, so ModelMaxLength isn't available there.

The template I'm talking about is the FieldInfoProvider template. But it's IMHO easier to generate a StringLengthAttribute on all string field properties. This is doable by a project attribute with a rule, no template change required (so no template to maintain, and the information is available at runtime)

To generate a StringLengthAttribute (from System.ComponentModel.DataAnnotations), please do the following:

  • Open Project settings, go to Entity Model -> Code Generation -> Attributes.
  • Select 'NormalField' for 'Element Type'.
  • Specify for attribute: System.ComponentModel.DataAnnotations.StringLength($length). Press TAB 2x and the row is added.
  • Click '...' next to it in 'Has rule'. A dialog pops up
  • Click the [+] button
  • Select 'Field Type' in the first combo box, and select 'string (System.String)' in the 3rd (available after 'Field type' is selected).
  • click OK.
  • Click OK to close the project settings.

The attribute is now defined. Generate source code. After generating source, you'll see that all string fields in entities have the attribute: [System.ComponentModel.DataAnnotations.StringLength(...)]

where ... is the length defined on the field.

At runtime you can then request the length using simple attribute reflection. You could e.g. do this in a validator injected in the entity.

If you want to alter the template instead, but again, you have to maintain it and port it to later versions (and v5.1 will alter it): - create new templatebindings file which binds SD_FieldInfoProviderTemplate to your copy (don't alter the vanilla templates, always work with copies) of the template SharedTemplates\Net3.5\C#\fieldInfoProvider.template. You can store this template in an additional templates folder set in the project settings. - On line 63, a change has to be made: <[SourceColumnMaxLength]> has to be replaced with <[FieldMaxLength]>. Remember the statement is there twice on the same line, as it has an if statement (it is done this way as TDL is a pattern matching language, not a turing complete programming language).

When generating code, the code generation dialog on tab 2 (click 'advanced') has to show your template bindings file. if not, click 'refresh code generation meta data' on the toolbar. v4 does allow you to save the templatebindings file at a location that's not reachable for the designer, so if it doesnt' show up, please check that first. If you see your templatebindings file, move it UP so it's above the shared templates bindings (so it overrules the binding of SD_FieldInfoProviderTemplate wink ). Generating code should now set the entity field length as the real length in the field info provider, so the field lengths known by the runtime are the ones defined in the entity editor. Setting a field now to a length > e.g. 50 (while still under 1GB) will then cause a validation error in the entity.

Frans Bouma | Lead developer LLBLGen Pro
kpeulic
User
Posts: 8
Joined: 29-Nov-2007
# Posted on: 12-Sep-2016 16:33:22   

Thanks for the help. simple_smile

We tried both options and choose custom template solution.

Regards... simple_smile