Group Join Problem

Posts   
 
    
Rakes
User
Posts: 2
Joined: 07-Aug-2019
# Posted on: 07-Aug-2019 02:42:24   

Same Linq query when written in VB.NET it is throwing "Unexpected expression type 'Unknown' found as source of DefaultIfEmpty(). Can't continue" exception in contrast to C# where it is working fine.

Snippet:

VB.NET (Not Working and throwing exception: Unexpected expression type 'Unknown' found as source of DefaultIfEmpty())

    Dim lnqQuery = New APHIM.Linq.LinqMetaData()
    Dim enumerable = (From ucs In lnqQuery.UnifiedCodeSet
                      Join domain In lnqQuery.V_Domain On ucs.Domain_ID Equals domain.ID
                      Group Join term In lnqQuery.TermDictionary On ucs.ID Equals term.TermCode_ID Into x = Group
                      From y In x.DefaultIfEmpty()
                      Where ucs.FullName = fullName AndAlso y.Name = termName
                      Select New With {.ID = ucs.ID})
    Dim result = enumerable.FirstOrDefault()

C#.NET (Working Fine)

        var lnqQuery = new APHIM.Linq.LinqMetaData();
        var enumerable = (from ucs in lnqQuery.UnifiedCodeSet
                          join domain in lnqQuery.V_Domain on ucs.Domain_ID equals domain.ID
                          join term in lnqQuery.TermDictionary on ucs.ID equals term.TermCode_ID into x
                          from y in x.DefaultIfEmpty()
                          where ucs.FullName==fullName && y.Name==termName 
                          select new {ID = ucs.ID});
        var result = enumerable.FirstOrDefault();
daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 07-Aug-2019 08:09:16   

What LLBLGen version and runtime library version are you using? ( http://www.llblgen.com/TinyForum/Messages.aspx?ThreadID=9076 )

Any reason why you are using Group Join and not the normal Join?

David Elizondo | LLBLGen Support Team
Rakes
User
Posts: 2
Joined: 07-Aug-2019
# Posted on: 07-Aug-2019 09:00:36   

I am using LLBLGenPro Version 5.4

Reason I wanted to have the Group join over the regular join because join to TermDictionary I need it to be left join.

Snippet I posted needs to be modified further.

The Query which I need to convert to Linq is as mentioned below:

SELECT TOP(@p2) [LPA_L1].[ID], [LPA_L1].[Code] FROM (([dbo].[UnifiedCodeSet] [LPA_L1] INNER JOIN [dbo].[Domain] [LPA_L2] ON [LPA_L1].[domain_ID] = [LPA_L2].[ID]) LEFT JOIN [dbo].[TermDictionary] [LPA_L3] ON [LPA_L1].[ID] = [LPA_L3].[termCode_ID]) WHERE ( ( ( ( ( ( [LPA_L2].[Name] = @p3) AND ( ( [LPA_L3].[ID] = @p4) OR ( [LPA_L3].[active] = @p5)))))))

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39590
Joined: 17-Aug-2003
# Posted on: 07-Aug-2019 09:56:44   

We'll see why this happens. Might be the VB.NET compiler generates a different expression tree and therefore things go wrong. GroupJoin should work OK

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39590
Joined: 17-Aug-2003
# Posted on: 07-Aug-2019 10:23:47   

Well, the Expression trees are different (which is what the compilers generate and what the linq handler has to deal with): the GroupJoin in C#:


    .GroupJoin(value(SD.LLBLGen.Pro.LinqSupportClasses.DataSource2`1[AdventureWorks.Dal.Adapter.EntityClasses.StoreContactEntity]),
              <>h__TransparentIdentifier0 => <>h__TransparentIdentifier0.c.ContactId, 
              sc => sc.ContactId, 
              (<>h__TransparentIdentifier0, csc) => 
                                    new <>f__AnonymousType1`2(<>h__TransparentIdentifier0 = <>h__TransparentIdentifier0, csc = csc))

and in VB.NET:


.GroupJoin(value(SD.LLBLGen.Pro.LinqSupportClasses.DataSource2`1[AdventureWorks.Dal.Adapter.EntityClasses.StoreContactEntity]), 
                $VB$It => $VB$It.c.ContactId, 
                sc => sc.ContactId, 
                ($VB$It, $VB$ItAnonymous) => new VB$AnonymousType_4`2($VB$It = $VB$It, x = $VB$ItAnonymous))

See the difference between csc=csc and x=$VB$ItAnonymous ? (property generated on the anonymous type has a name different from the argument)

Looking into it (as there should be code to deal with this)

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39590
Joined: 17-Aug-2003
# Posted on: 07-Aug-2019 11:25:45   

The main problem is indeed that in VB.NET, the target of the group join (whether you specify x=Group or just Group) is a member which name is unknown to the handler at this point: in VB.NET the value is passed on through an anonymous parameter in the lambda (as you can see above) and in C# it's passed on as a parameter with the same name.

Anonymous types at runtime get properties with the same name as mentioned in the constructor call. I have no idea why they do it this way, as e.g. in the SelectMany they do it OK. disappointed

Anyway, we have to add a visitor specifically for this to determine the name of the member a given parameter is assigned to in a constructor call of an anonymous type through a lambda, and this is specifically for this situation.

The VB.NET team did their users a huge disservice with their weird expression tree emitter as this mess is unnecessary (and it's not the only occasion things are specifically different for VB.NET only).

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39590
Joined: 17-Aug-2003
# Posted on: 07-Aug-2019 14:35:45   

Fixed.

See 5.4.7 hotfix build for the fix for 5.4. Also fixed in 5.5.4 hotfix.

Frans Bouma | Lead developer LLBLGen Pro