Left Join with Distinct

Posts   
 
    
rossmcw
User
Posts: 28
Joined: 27-Mar-2008
# Posted on: 08-Apr-2008 07:02:55   

I am having an issue where by if I left join in conjunction with a .Distinct() I am getting an internal error.

db is LinqMetaData for Northwind.

                var ord = (
                     from c in db.Customers
                     join o in db.Orders on c.CustomerID equals o.CustomerID into og
                     from o in og.DefaultIfEmpty()
                     join od in db.OrderDetails on o.OrderID equals od.OrderID into odg
                     from od in og.DefaultIfEmpty()
                     select new
                     {
                         c.CustomerID,
                         od.OrderDate
                     }
                 ).Distinct();

This dies before any SQL generation with 'Internal error: QueryExpression of non-entity type without projection encountered without prior source with projection.' If I remove distinct it works.

If I replace the select new {} with just select u, and using distinct SQL is generated but the aliases are confused:

SELECT DISTINCT 
    [LPA_L4].[CustomerID], 
    [LPA_L4].[CompanyName], 
    [LPA_L4].[ContactName], 
    [LPA_L4].[ContactTitle], 
    [LPA_L4].[Address], 
    [LPA_L4].[City], 
    [LPA_L4].[Region], 
    [LPA_L4].[PostalCode], 
    [LPA_L4].[Country], 
    [LPA_L4].[Phone], 
    [LPA_L4].[Fax] 
FROM (( 
    [Northwind].[dbo].[Customers] [LPA_L1]  
    LEFT JOIN [Northwind].[dbo].[Orders] [LPA_L2]  
        ON  [LPA_L1].[CustomerID] = [LPA_L2].[CustomerID]) 
    LEFT JOIN [Northwind].[dbo].[Orders] [LPA_L3]  
        ON  [LPA_L1].[CustomerID] = [LPA_L3].[CustomerID])

Where it looks like [LPA_L4] should be [LPA_L1]. Now if I drop the distinct the query runs with the correct alias, but interestingly with a distinct.

SELECT DISTINCT 
    [LPA_L1].[CustomerID], 
    [LPA_L1].[CompanyName], 
    [LPA_L1].[ContactName], 
    [LPA_L1].[ContactTitle], 
    [LPA_L1].[Address], 
    [LPA_L1].[City], 
    [LPA_L1].[Region], 
    [LPA_L1].[PostalCode], 
    [LPA_L1].[Country], 
    [LPA_L1].[Phone], 
    [LPA_L1].[Fax] 
FROM (( 
    [Northwind].[dbo].[Customers] [LPA_L1]  
    LEFT JOIN [Northwind].[dbo].[Orders] [LPA_L2]  
        ON  [LPA_L1].[CustomerID] = [LPA_L2].[CustomerID]) 
    LEFT JOIN [Northwind].[dbo].[Orders] [LPA_L3] 
        ON  [LPA_L1].[CustomerID] = [LPA_L3].[CustomerID])

I know this example is a bit trivial and pointless and that I could have done some stuff that is possibly not supported by Linq to LLBLGen, but the behavior does seems a little odd.

Many thanks, Ross

[edit] Just looking at the above generated SQL, it looks seems to be joining to [Orders] twice rather that [orders] and [order details]. Thats [Order details] with a space... I wonder if that has anything to do with anything.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39903
Joined: 17-Aug-2003
# Posted on: 08-Apr-2008 09:34:30   

The distinct you see with the entity fetch is normal, llblgen pro always emits a distinct in that case to avoid duplicates.

The errors you run into shouldn't happen, I'll check it out.!

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39903
Joined: 17-Aug-2003
# Posted on: 08-Apr-2008 10:17:14   

The exception on your first query occurs because the projection of the query is inside the join statement and although there's code in place which pulls this out of the join, it has a bug where it doesn't work if it's not the most outer query.

This is a special case. It fails with any extension method appended to the join query which doesn't do a projection: the QueryExpression which is the result of the 'Distinct' call is merged with the join's QueryExpression, but the projection of the Join isn't used.

I'll fix that.

The wrong SQL is caused by the same issue actually: there's no projection found and it tries to re-construct the projection from the resulttype.

(edit)

[edit] Just looking at the above generated SQL, it looks seems to be joining to [Orders] twice rather that [orders] and [order details]. Thats [Order details] with a space... I wonder if that has anything to do with anything.

That's because your second DefaultIfEmpty call is again on 'og', instead of 'odg', so 'od' is also of type 'Order', hence the join twice. Your original query wouldn't compile otherwise as od doesn't have 'OrderDate'.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39903
Joined: 17-Aug-2003
# Posted on: 08-Apr-2008 13:00:28   

Ok, that took a while simple_smile But I have it fixed. Please use the attached dll (which works with the latest beta batch).

Frans Bouma | Lead developer LLBLGen Pro
rossmcw
User
Posts: 28
Joined: 27-Mar-2008
# Posted on: 08-Apr-2008 23:25:52   

Thanks, I cant see an attachment tho, but I wouldnt be able to just drop it into our development environment anyway, as we hand roll our LLBLGen runtimes to use a different namespace. I will have wait for the next source release. I also have couple of other issues which I will post later today hopefully.

Oh and oops, my bad on the 'odg' typo, actually a very easy typo to make due to the slightly awkward way Linq does left joins.

Thanks again, Ross

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39903
Joined: 17-Aug-2003
# Posted on: 09-Apr-2008 09:33:10   

Hmm, indeed the attachment is missing flushed . I re-uploaded the dll a couple of times as I forgot to update the build nr. etc. (It's on another machine so I can't access it right now, will upload when that machine is back up)

Anyway, it would be great if you could post the other problems so we can fix them too and include it into the next build. The longer it takes to fix these problems, the more chance we run to miss a few before release.

So next time, please post all problems you run into, thanks simple_smile

Frans Bouma | Lead developer LLBLGen Pro
rossmcw
User
Posts: 28
Joined: 27-Mar-2008
# Posted on: 09-Apr-2008 13:21:07   

Will do. Will post details when I get into work tomorrow (nighttime european time), I just couldn't get 5mins today. simple_smile

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39903
Joined: 17-Aug-2003
# Posted on: 09-Apr-2008 14:08:08   

rossmcw wrote:

Will do. Will post details when I get into work tomorrow (nighttime european time), I just couldn't get 5mins today. simple_smile

No problem. simple_smile I made some changes to the runtime libs as well, so attaching a new dll isn't really working (will break). I'll wait for the other errors you'll report so I can fix them and include them in the next build. simple_smile

Frans Bouma | Lead developer LLBLGen Pro