Doubly nested entity in derived model causing incorrect generated code in CreateProjectionFunc method

Posts   
 
    
Posts: 98
Joined: 10-Nov-2006
# Posted on: 16-Feb-2017 22:43:02   

LLBLGen version 5.1.1 Adapter Platform: .NET 4.5.2 Language: C# Framework: DTO Class Model Preset: SD.DTOClasses.ReadOnlyDTOs SQL Server

I have a entity model with 3 entities:

Client (ClientId int PK, Name varchar(10)) Project (ProjectId int PK, Name varchar(10), ClientId int FK) Section (SectionId int PK, Name varchar(10), ProjectId int FK)

In other words, a Section has 1 related Project, and a Project has a 1 related Client.

I'm using the designer to create a Derived Model based on Section. In the tree in the "Derived Element Sub-Element Selection" area, I choose the fields I want from Section, then open the "Project" subtree and select Name and ProjectId. Then, within the "Project" subtree, I open the "Client" sub-sub tree and select Name and ClientId.

Next, in the "Derived Element Shape Editor", I select the Project's Name and Id fields and press "De-normalize selected fields". Those fields move into the main Element. I then select the Client's Name and Id fields and press "De normalize selected fields" twice - once to move them up to the Project embedded element, and again to move them into the main Element.

At this point, I'm done, so I save the project.

If I look at the project file at this point, all seems well, and it's saving the nested relationships as expected:

 <Field Name="ProjectName">
              <EntityField Name="Name" Entity=":Project" NavigatorPath="Project" />
 </Field>
 <Field Name="ProjectProjectId">
              <EntityField Name="ProjectId" Entity=":Project" NavigatorPath="Project" />
 </Field>
 <Field Name="ClientClientId">
              <EntityField Name="ClientId" Entity=":Client" NavigatorPath="Project,Client" />
 </Field>
 <Field Name="ClientName">
              <EntityField Name="Name" Entity=":Client" NavigatorPath="Project,Client" />
 </Field>

I then generate the code.

In the DTO, all seems good and the comments are correct:

/// <summary>Gets or sets the ClientClientId field. Derived from Entity Model Field 'Client.ClientId'</summary>
[DataMember]
public System.Int32 ClientClientId { get; set; }

/// <summary>Gets or sets the ClientName field. Derived from Entity Model Field 'Client.Name'</summary>
[DataMember]
public System.String ClientName { get; set; }

/// <summary>Gets or sets the ProjectName field. Derived from Entity Model Field 'Project.Name (Project)'</summary>
[DataMember]
public System.String ProjectName { get; set; }

/// <summary>Gets or sets the ProjectProjectId field. Derived from Entity Model Field 'Project.ProjectId (Project)'</summary>
[DataMember]
public System.Int32 ProjectProjectId { get; set; }

But in the Persistence class, it's wrong:


private static System.Linq.Expressions.Expression<Func<GreaterGiving.Data.AdapterData.EntityClasses.SectionEntity, GreaterGiving.Data.Audit.DtoClasses.SectionAudit>> CreateProjectionFunc()
        {
            return p__0 => new GreaterGiving.Data.Audit.DtoClasses.SectionAudit()
            {
                ClientClientId = p__0.ClientId,
                ClientName = p__0.Name,
                ProjectName = p__0.Project.Name,
                ProjectProjectId = p__0.Project.ProjectId,
                SectionId = p__0.SectionId,
            };
        }
        

Note that the 2 "Project" fields are correct - they correctly get their data from properties of p__0.Project. But the "Client" fields are wrong. For example, ClientName is set from p__0.Name, but it should be p__0.Project.Client.Name.

Thus, the generated code doesn't compile.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 17-Feb-2017 17:36:13   

Looks like a template bug indeed. We'll look into it!

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 20-Feb-2017 13:30:11   

Reproduced

(edit). The error is in loading the navigation path when loading the project: it simply doesn't handle multiple entities well and as the second navigator doesn't match the containing entity (as it's from another entity) it can't find it and ignores it. If you generate code right after denormalizing the fields, it will work, when saving / reloading the project, it won't. You'll also see that when loading the project, the navigation path behind the field in the shape editor isn't properly defined anymore.

It also has the consequence that if you save again after loading the project, the path is gone and you have to correct it manually again. This is something we can't fix after we correct the issue with the loader. After we've fixed this, you have to: delete the fields from the document, then re add them, denormalize them again.

Looking into how to fix this (broken in 5.0.x too)

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 20-Feb-2017 16:43:36   

Fixed in 5.0.10 and 5.1.3. Both versions have an updated hotfix build which is now available under MyAccount downloads.

With this particular issue, if the project file still contains the proper path information (e.g. NavigatorPath="Project,Client" />) then the fixed build will load your project normally and the generated code is correct. If you already saved the project again and thus lost this info, you have to remove the fields and again select the fields in the shape editor and denormalize them.

Frans Bouma | Lead developer LLBLGen Pro
Posts: 98
Joined: 10-Nov-2006
# Posted on: 20-Feb-2017 23:25:13   

I was using the command line CliGenerator.exe to generate my project files, so that explains why it was failing for me consistently (the project was being loaded and parsed on each run of the tool).

I've installed the hotfix, and the generated file is now correct. Thanks for the fix!