Sorting field for TypedViews and TypedLists

Posts   
 
    
MJC
User
Posts: 50
Joined: 06-May-2004
# Posted on: 11-May-2013 08:39:07   

I'm trying to figure out how to reproduce the following code, but using a C# lpt template.


<[Foreach TypedView]>   /// <summary>Index enum to fast-access Typed View EntityFields in the IEntityFields collection for the typed view : <[CurrentTypedViewName]>.</summary>
    public enum <[CurrentTypedViewName]>FieldIndex
    {
<[Foreach TypedViewField CommaCrLf]>        ///<summary><[TypedViewFieldName]></summary>
        <[TypedViewFieldName]><[NextForeach]><[If HasFields]>,<[EndIf]>
        /// <summary></summary>
        AmountOfFields
    }
<[NextForeach]>
<[ Foreach TypedList]>  /// <summary>Index enum to fast-access TypedList Fields in the Columns collection of the Typed List: <[ CurrentTypedListName ]></summary>
    public enum <[CurrentTypedListName]>TypedListFieldIndex
    {
<[Foreach TypedListField CommaCrLf]>        ///<summary><[TypedListFieldName]></summary>
        <[TypedListFieldName]><[NextForeach]><[If HasFields]>,<[EndIf]>
        /// <summary></summary>
        AmountOfFields
    }
<[ NextForeach ]>

If I do this in the lpt template, I can't figure out how to get the fields in the right order. I've tried by field index, name, and no ordering (i.e.: typedViewDefinition.Fields), but it doesn't give me the right order. How do I translate the above from a TDL template to an LPT template?

MJC
User
Posts: 50
Joined: 06-May-2004
# Posted on: 12-May-2013 01:32:11   

I wasn't thinking it through enough it looks like. I think I figured out the solution for Typed Views, which is to reach down into the MappedTarget of the TypedView, which makes sense.

The following seems to give me what I'm looking for:


var item = (TypedViewDefinition)_activeObject;

//The following doesn't give you proper ordering, the FieldIndex is often equal to -1 
//var fields = item.Fields.OrderBy(f => f.FieldIndex).ToList();   

//Use the explicit field ordering if it exists, OR, use ordering from the fields on the mapped target (actual db view)
var mapping = (TypedViewMapping)_executingGenerator.ProjectDefinition.GetGroupableModelElementMapping(item, _executingGenerator.DriverID);
var fields = item.Fields.HasFieldOrdering ? item.Fields.ApplyFieldOrdering().ToList():
               item.Fields.OrderBy(f => mapping.GetFieldMappingOfField(f).MappedTarget.OrdinalPosition).ToList();

Let me know if this isn't correct, or if there's a better way.

As far as Typed Lists, the ordering seems to be fine simply with ((TypedListDefinition)_activeObject).Fields

Btw, the reason I needed this was to properly order the grid for Typed Views in my demo here http://northwind.mattjcowan.com/views , and the grid for Typed Lists here http://northwind.mattjcowan.com/lists

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 13-May-2013 07:12:55   

Hi MJC,

  • What LLBLGen version are you using?

  • Your code seems to be right, however I wonder whether or not it should work just with item.Fields, just like Entity or TypedList.

David Elizondo | LLBLGen Support Team
MJC
User
Posts: 50
Joined: 06-May-2004
# Posted on: 13-May-2013 08:52:42   

You made me think that maybe I should try to do a "Refresh from Relational Database", so I did that, and the llblgen project file was modified as follows:

Before:


    <TypedViewDefinition Name="OrdersQry">
      <Fields>
        <Field Name="Address" Type="string" IsOptional="true" MaxLength="60" />
        <Field Name="City" Type="string" IsOptional="true" MaxLength="15" />
        <Field Name="CompanyName" Type="string" MaxLength="40" />
        <Field Name="Country" Type="string" IsOptional="true" MaxLength="15" />
        <Field Name="CustomerId" Type="string" IsOptional="true" MaxLength="5" />
        <Field Name="EmployeeId" Type="int" IsOptional="true" Precision="10" />
        <Field Name="Freight" Type="decimal" IsOptional="true" Precision="19" Scale="4" />
        <Field Name="OrderDate" Type="datetime" IsOptional="true" />
        <Field Name="OrderId" Type="int" Precision="10" />
        <Field Name="PostalCode" Type="string" IsOptional="true" MaxLength="10" />
        <Field Name="Region" Type="string" IsOptional="true" MaxLength="15" />
        <Field Name="RequiredDate" Type="datetime" IsOptional="true" />
        <Field Name="ShipAddress" Type="string" IsOptional="true" MaxLength="60" />
        <Field Name="ShipCity" Type="string" IsOptional="true" MaxLength="15" />
        <Field Name="ShipCountry" Type="string" IsOptional="true" MaxLength="15" />
        <Field Name="ShipName" Type="string" IsOptional="true" MaxLength="40" />
        <Field Name="ShippedDate" Type="datetime" IsOptional="true" />
        <Field Name="ShipPostalCode" Type="string" IsOptional="true" MaxLength="10" />
        <Field Name="ShipRegion" Type="string" IsOptional="true" MaxLength="15" />
        <Field Name="ShipVia" Type="int" IsOptional="true" Precision="10" />
      </Fields>

After:



    <TypedViewDefinition Name="OrdersQry">
      <Fields>
        <Field Name="Address" Type="string" IsOptional="true" MaxLength="60" FieldIndex="15" />
        <Field Name="City" Type="string" IsOptional="true" MaxLength="15" FieldIndex="16" />
        <Field Name="CompanyName" Type="string" MaxLength="40" FieldIndex="14" />
        <Field Name="Country" Type="string" IsOptional="true" MaxLength="15" FieldIndex="19" />
        <Field Name="CustomerId" Type="string" IsOptional="true" MaxLength="5" FieldIndex="1" />
        <Field Name="EmployeeId" Type="int" IsOptional="true" Precision="10" FieldIndex="2" />
        <Field Name="Freight" Type="decimal" IsOptional="true" Precision="19" Scale="4" FieldIndex="7" />
        <Field Name="OrderDate" Type="datetime" IsOptional="true" FieldIndex="3" />
        <Field Name="OrderId" Type="int" Precision="10" FieldIndex="0" />
        <Field Name="PostalCode" Type="string" IsOptional="true" MaxLength="10" FieldIndex="18" />
        <Field Name="Region" Type="string" IsOptional="true" MaxLength="15" FieldIndex="17" />
        <Field Name="RequiredDate" Type="datetime" IsOptional="true" FieldIndex="4" />
        <Field Name="ShipAddress" Type="string" IsOptional="true" MaxLength="60" FieldIndex="9" />
        <Field Name="ShipCity" Type="string" IsOptional="true" MaxLength="15" FieldIndex="10" />
        <Field Name="ShipCountry" Type="string" IsOptional="true" MaxLength="15" FieldIndex="13" />
        <Field Name="ShipName" Type="string" IsOptional="true" MaxLength="40" FieldIndex="8" />
        <Field Name="ShippedDate" Type="datetime" IsOptional="true" FieldIndex="5" />
        <Field Name="ShipPostalCode" Type="string" IsOptional="true" MaxLength="10" FieldIndex="12" />
        <Field Name="ShipRegion" Type="string" IsOptional="true" MaxLength="15" FieldIndex="11" />
        <Field Name="ShipVia" Type="int" IsOptional="true" Precision="10" FieldIndex="6" />
      </Fields>

And the Field Indexes were set, so yeah, now item.Fields will work and FieldIndexes are no longer -1.

So I now realize I probably had a wrong assumption that: "setting the 'Reset order upon refresh' flag on the project BEFORE reverse engineering tables and views into the project would set the field order correctly'. You truly have to run the refresh command, after first reverse-engineering. The name of that setting should have tipped me off.

To validate, I tried on V4 of llblgen as follows: - created a new project - set the flag in the designer and saved the project <Property Name="ResetFieldOrderBasedOnTargetOrderAtRefresh" Value="true" /> - imported the Northwind database and reverse engineered the tables into entities, and views into typed views - item.Fields returns the fields ordered by name (fieldindex = -1) - did a refresh - item.Fields now the order that first expected and field indexes are set

It would be nice IMO simple_smile if the field order was set correctly after first reverse engineering the tables/views when that field is set, instead of requiring a refresh. Or maybe I'm missing something and this can already be done.

I don't know why this escaped me. At least I know what's going on now, and I'll make sure to refresh all projects consistently from now on.

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 13-May-2013 20:35:03   

For working database-first, this is done during a catalog refresh if the project property ResetFieldOrderBasedOnTargetOrderAtRefresh is set to true (default is false). When reverse engineering, new entities created through reverse engineering will only get their fields ordered after the ordinal ordering of the fields of the tables/views they're mapped on if the project property **UseCustomFieldOrderingOnNewElements **is set to true (false by default).

ref: Field Ordering

MJC
User
Posts: 50
Joined: 06-May-2004
# Posted on: 13-May-2013 21:00:43   

I create a new project, and have both the properties set in the llblgenproj file as follows, before I do any schema imports and reverse engineering:


<Property Name="ResetFieldOrderBasedOnTargetOrderAtRefresh" Value="true" />
<Property Name="UseCustomFieldOrderingOnNewElements" Value="true" />

The project is saved, I import the northwind db, reverse engineer, and fields are still sorted alphabetically in the Typed Views. The fields in the entities are sorted based on how they are in the database, so UseCustomFieldOrderingOnNewElements is being used, but typed views are still sorted alphabetically without a FieldIndex in the llblgenproj file.

If I then do a refresh, the fields are sorted in the Typed Views as expected.

It doesn't seem to me the "UseCustomFieldOrderingOnNewElements" is applying itself to TypedViews.

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 14-May-2013 08:35:10   

I reproduced the behavior in your last post. The documentation says that this works for "Refreshes", so it's not clear to me whether this is expected or not. But clearly it works for Entities, not for TypecViews. We will look into it.

David Elizondo | LLBLGen Support Team
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 14-May-2013 17:14:19   

The setting UseCustomFieldOrderingOnNewElements is meant for entities and doesn't have any effect on typedviews. Reading your post it's indeed a bit strange that a typedview doesn't get the field indexes when you create a new typedview. We'll fix this in v4.0

Frans Bouma | Lead developer LLBLGen Pro
MJC
User
Posts: 50
Joined: 06-May-2004
# Posted on: 14-May-2013 17:59:19   

No problem, thanks guys for checking into it. I wonder if it would be worthwhile having a setting like "UseCustomFieldOrderingOnNewElements" for Typed Views. In the meantime, the refresh works well and I can manage with that without issue.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 14-May-2013 18:15:02   

I think it's 2 lines of code, so it's not a big fix, will be available tomorrow simple_smile

Frans Bouma | Lead developer LLBLGen Pro
MJC
User
Posts: 50
Joined: 06-May-2004
# Posted on: 14-May-2013 18:53:39   

Nice! smile

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 15-May-2013 11:09:38   

done simple_smile

Frans Bouma | Lead developer LLBLGen Pro