Incorrect join when master-detail have same fieldname that join is done on

Posts   
 
    
TomDog
User
Posts: 623
Joined: 25-Oct-2005
# Posted on: 14-Jan-2011 12:40:57   

This a hell of an edge case but I seem to keep hitting them. I can't quite repro in northwind but I hope you can follow it. This query in LINQPad

var x = from o in Order
from od in o.OrderDetails
where o.OrderId==10347
select new {o, od};

var z = from y in x
select new {y.o.OrderId, y.od.Product.ProductName};
z.Dump();

produces this SQL

DECLARE @p1 Int; SET @p1=10347
SELECT [LPA_L1].[OrderId],
  [LPA_L2].[ProductName]
FROM
 ((SELECT [LPA_L4].[CustomerID] AS [CustomerId],
  [LPA_L4].[EmployeeID] AS [EmployeeId],
  [LPA_L4].[Freight],
  [LPA_L4].[OrderDate],
  [LPA_L4].[OrderID] AS [OrderId],
  [LPA_L4].[RequiredDate],
  [LPA_L4].[ShipAddress],
  [LPA_L4].[ShipCity],
  [LPA_L4].[ShipCountry],
  [LPA_L4].[ShipName],
  [LPA_L4].[ShippedDate],
  [LPA_L4].[ShipPostalCode],
  [LPA_L4].[ShipRegion],
  [LPA_L4].[ShipVia],
  [LPA_L5].[Discount],
  [LPA_L5].[OrderID] AS [OrderId0],
  [LPA_L5].[ProductID] AS [ProductId],
  [LPA_L5].[Quantity],
  [LPA_L5].[UnitPrice]
FROM
 ( [Northwind].[dbo].[Orders] [LPA_L4] 
INNER JOIN
 [Northwind].[dbo].[Order Details] [LPA_L5]  ON  [LPA_L4].[OrderID]=[LPA_L5].[OrderID])
WHERE
 ( ( ( [LPA_L4].[OrderID] = @p1)))) [LPA_L1]
INNER JOIN
 [Northwind].[dbo].[Products] [LPA_L2]  ON  [LPA_L2].[ProductID]=[LPA_L1].[ProductId])

which is all fine and good. But if Orders had a field called ProductID as well as [Order Details] then the final join would be wrong because of the subsequent field rename. i.e. the SQL would be something like

DECLARE @p1 Int; SET @p1=10347
SELECT [LPA_L1].[OrderId],
  [LPA_L2].[ProductName]
FROM
 ((SELECT [LPA_L4].[CustomerID] AS [CustomerId],
  [LPA_L4].[EmployeeID] AS [EmployeeId],
  [LPA_L4].[Freight],
  [LPA_L4].[OrderDate],
  [LPA_L4].[OrderID] AS [OrderId],
  [LPA_L4].[ProductID] AS [ProductId],
  [LPA_L4].[RequiredDate],
  [LPA_L4].[ShipAddress],
  [LPA_L4].[ShipCity],
  [LPA_L4].[ShipCountry],
  [LPA_L4].[ShipName],
  [LPA_L4].[ShippedDate],
  [LPA_L4].[ShipPostalCode],
  [LPA_L4].[ShipRegion],
  [LPA_L4].[ShipVia],
  [LPA_L5].[Discount],
  [LPA_L5].[OrderID] AS [OrderId0],
  [LPA_L5].[ProductID] AS [ProductId0],
  [LPA_L5].[Quantity],
  [LPA_L5].[UnitPrice]
FROM
 ( [Northwind].[dbo].[Orders] [LPA_L4] 
INNER JOIN
 [Northwind].[dbo].[Order Details] [LPA_L5]  ON  [LPA_L4].[OrderID]=[LPA_L5].[OrderID])
WHERE
 ( ( ( [LPA_L4].[OrderID] = @p1)))) [LPA_L1]
INNER JOIN
 [Northwind].[dbo].[Products] [LPA_L2]  ON  [LPA_L2].[ProductID]=[LPA_L1].[ProductId])

which is the problem I'm hitting were the last line should be [Northwind].[dbo].[Products] [LPA_L2] ON [LPA_L2].[ProductID]=[LPA_L1].[ProductId0])

I can work around it but I'm hoping it's an easy fix.

linq 3.0.11.113 and orm support 3.0.10.1201

Jeremy Thomas
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39908
Joined: 17-Aug-2003
# Posted on: 17-Jan-2011 10:23:03   

I see what you mean, however the information which fields of which entity were renamed is not stored somewhere, so if some other query refers to the element's fields (like you do with select new {y.o.OrderId, y.od.Product.ProductName};, it's not known y.od comes from the 'od' element in the previous query and its fields are renamed, so y.od.Product will need to use ProductID0. The renaming takes place at a low level, and it doesn't store information for outer query usage. This perhaps should be done, but isn't done at the moment. So 'easy fix' isn't possible unfortunately, otherwise I'd have fixed it for you. disappointed

Frans Bouma | Lead developer LLBLGen Pro
TomDog
User
Posts: 623
Joined: 25-Oct-2005
# Posted on: 18-Jan-2011 03:09:51   

Otis wrote:

I see what you mean, however the information which fields of which entity were renamed is not stored somewhere, so if some other query refers to the element's fields (like you do with select new {y.o.OrderId, y.od.Product.ProductName};, it's not known y.od comes from the 'od' element in the previous query and its fields are renamed, so y.od.Product will need to use ProductID0. The renaming takes place at a low level, and it doesn't store information for outer query usage. This perhaps should be done, but isn't done at the moment. So 'easy fix' isn't possible unfortunately, otherwise I'd have fixed it for you. disappointed

Ok in that case I've done something 'easy' at my end - renamed the conflicting property of one of the entities, no drama.

Jeremy Thomas