How to do a where in subquery using Entity Framework? - c#

I have a query like:
var result = from u in this.DataContext.Users
join l in DataContext.Locations on u.Id equals l.userId
where u.active == 1
select u;
return result ;
I want to add a subquery WHERE IN clause like:
WHERE u.Id IN (SELECT userId FROM approved_users)
Is this possible?

I am not sure why you want it in a sub query, it seems simpler to just join the Approved Users table, but I do not know the requirement so I have presented two options. One option that has a sub query and one option with the additional join. I am also making an assumption that you don't have any navigation properties.
Option 1 - Subquery:
var subQuery =
from u in context.Users.Where(x => context.ApprovedUsers.Select(y => y.ApprovedUserId).Contains(x.UserId))
join l in context.Locations on u.UserId equals l.UserId
where u.IsActive == true
select u;
which generates something like this
SELECT
[Extent1].[UserId] AS [UserId],
[Extent1].[Name] AS [Name],
[Extent1].[IsActive] AS [IsActive]
FROM [dbo].[User] AS [Extent1]
INNER JOIN [dbo].[Location] AS [Extent2] ON [Extent1].[UserId] = [Extent2].[UserId]
WHERE ( EXISTS (SELECT
1 AS [C1]
FROM [dbo].[ApprovedUser] AS [Extent3]
WHERE [Extent3].[ApprovedUserId] = [Extent1].[UserId]
)) AND (1 = [Extent1].[IsActive])
Option 2 - Additional Join:
var query =
from u in context.Users
join l in context.Locations on u.UserId equals l.UserId
join au in context.ApprovedUsers on u.UserId equals au.ApprovedUserId
where u.IsActive == true
select u;
which generates:
SELECT
[Extent1].[UserId] AS [UserId],
[Extent1].[Name] AS [Name],
[Extent1].[IsActive] AS [IsActive]
FROM [dbo].[User] AS [Extent1]
INNER JOIN [dbo].[Location] AS [Extent2] ON [Extent1].[UserId] = [Extent2].[UserId]
INNER JOIN [dbo].[ApprovedUser] AS [Extent3] ON [Extent1].[UserId] = [Extent3].[ApprovedUserId]
WHERE 1 = [Extent1].[IsActive]

Related

How to improve LINQ statement to use INNER JOIN in resulting SQL statement?

Assuming the following code that applies filtering logic to a passed on collection.
private IQueryable<Customer> ApplyCustomerFilter(CustomerFilter filter, IQueryable<Customer> customers)
{
...
if (filter.HasProductInBackOrder == true)
{
customers = customers.Where(c => c.Orders.Any(o => o.Products.Any(p => p.Status == ProductStatus.BackOrder)))
}
....
return customers;
}
Results in this SQL statement:
SELECT [Extent1].[CustomerId] AS [CustomerId],
[Extent1].[Status] AS [Status]
FROM [Customers] AS [Extent1]
WHERE
(
EXISTS
(
SELECT 1 AS [C1]
FROM
(
SELECT [Extent3].[OrderId] AS [OrderId]
FROM [Orders] AS [Extent3]
WHERE [Extent1].[CustomerId] = [Extent3].[CustomerId]
) AS [Project1]
WHERE EXISTS
(
SELECT 1 AS [C1]
FROM [Products] AS [Extent4]
WHERE ([Project1].[OrderId] = [Extent4].[OrderId])
AND ([Extent4].[Status] = #p__linq__6)
)
)
)
However, I would like to optimize this by forcing to use INNER JOINS so that the result will be similar to this:
SELECT [Extent1].[CustomerId] AS [CustomerId],
[Extent1].[Status] AS [Status]
FROM [Customers] AS [Extent1]
INNER JOIN [Orders] AS [Extent2] ON [Extent1].[CustomerId] = [Extent2].[CustomerId]
INNER JOIN [Products] AS [Extent3] ON [Extent2].[OrderId] = [Extent3].[OrderId]
WHERE [Extent3].[Status] = #p__linq__6
I've tried multiple approaches, but I was unable to accomplish the desired result. Any suggestions on how to force the correct joins and avoiding subselects?

LINQ to SQL LEFT JOIN, GROUP BY, COUNT, MAX and subquery

I have 3 tables: Users, Roles, Bids.
Two of them is created by ASP.NET Identity, Bids is my custom table (it is secondary to Users table)
I'm trying to get all users that aren't in specific role (all non admin users) and show number of bids (they can be null - I have left join), show highest bid per user and show if that bid is max.
SQL query was quire easy:
SELECT
U.Id
,U.UserName
,U.Email
,ISNULL(MAX(B.PriceInPLN), 0)
,COUNT(B.BidID)
,IIF(MAX(B.PriceInPLN)=(SELECT TOP 1 PriceInPLN FROM Bids B2 (NOLOCK) ORDER BY PriceInPLN DESC),1,0 ) AS Max
FROM
AspNetUsers U ( NOLOCK )
JOIN AspNetUserRoles UR ( NOLOCK ) ON U.Id = UR.UserId
LEFT JOIN Bids B ( NOLOCK ) ON B.ApplicationUserId = U.Id
WHERE
UR.RoleId != '9508f9d2-12fb-4175-89a7-3275cb7616ae'
GROUP BY
U.Id
,U.UserName
,U.Email
But I have trouble creating correct LINQ query. Here is what I have so far:
var users =(
from u in db.Users
where !u.Roles.Select(r => r.RoleId).Contains(adminRoleId)//everyone except admins
join b in db.Bids on u equals b.ApplicationUser into ub
from subset in ub.DefaultIfEmpty()//LEFT JOIN
group subset by new { u.Id, u.UserName, u.Email, u.EmailConfirmed, u.Online } into grouped
select new UserReturnModel
{
Id = grouped.Key.Id,
Name = grouped.Key.UserName,
Email = grouped.Key.Email,
EmailConfirmed = grouped.Key.EmailConfirmed,
Online = grouped.Key.Online,
BidsCount = grouped.Count(c => c.ApplicationUserId == grouped.Key.Id),
PriceInPLN = grouped.Max(c => c.PriceInPLN),
IsMax = (grouped.Max(c=>c.PriceInPLN) == db.Bids.Max(b=>b.PriceInPLN))
}).ToList();
I can't get Max column to work correctly - it always says true.
Here are column definitions to easily show what I want to get:
Id = user id,
Name = user name,
Email = user email,
BidsCount = number of bids created by that user,
PriceInPLN = max price for that user,
IsMax = is this user offer highest comparing to other offers, if there are no offers this should be false
I'm using that in ASP.NET, when debugging I've noticed that SQL query created by LINQ is large:
SELECT
1 AS [C1],
[Project6].[Id] AS [Id],
[Project6].[UserName] AS [UserName],
[Project6].[Email] AS [Email],
[Project6].[EmailConfirmed] AS [EmailConfirmed],
[Project6].[Online] AS [Online],
[Project6].[C4] AS [C2],
[Project6].[C1] AS [C3],
CASE WHEN (([Project6].[C2] = [GroupBy3].[A1]) OR (([Project6].[C2] IS NULL) AND ([GroupBy3].[A1] IS NULL))) THEN cast(1 as bit) WHEN ( NOT (([Project6].[C3] = [GroupBy4].[A1]) AND ((CASE WHEN ([Project6].[C3] IS NULL) THEN cast(1 as bit) ELSE cast(0 as bit) END) = (CASE WHEN ([GroupBy4].[A1] IS NULL) THEN cast(1 as bit) ELSE cast(0 as bit) END)))) THEN cast(0 as bit) END AS [C4]
FROM (SELECT
[Project3].[C1] AS [C1],
[Project3].[C2] AS [C2],
[Project3].[C3] AS [C3],
[Project3].[Id] AS [Id],
[Project3].[Online] AS [Online],
[Project3].[Email] AS [Email],
[Project3].[EmailConfirmed] AS [EmailConfirmed],
[Project3].[UserName] AS [UserName],
(SELECT
COUNT(1) AS [A1]
FROM ( SELECT
[Extent4].[Id] AS [Id],
[Extent4].[Online] AS [Online],
[Extent4].[Email] AS [Email],
[Extent4].[EmailConfirmed] AS [EmailConfirmed],
[Extent4].[UserName] AS [UserName],
[Extent5].[ApplicationUserId] AS [ApplicationUserId]
FROM [dbo].[AspNetUsers] AS [Extent4]
INNER JOIN [dbo].[Bids] AS [Extent5] ON [Extent5].[ApplicationUserId] = [Extent4].[Id]
WHERE ( NOT EXISTS (SELECT
1 AS [C1]
FROM [dbo].[AspNetUserRoles] AS [Extent6]
WHERE ([Extent4].[Id] = [Extent6].[UserId]) AND ([Extent6].[RoleId] = #p__linq__0)
)) AND ([Project3].[Id] = [Extent4].[Id]) AND ([Project3].[UserName] = [Extent4].[UserName]) AND (([Project3].[Email] = [Extent4].[Email]) OR (([Project3].[Email] IS NULL) AND ([Extent4].[Email] IS NULL))) AND ([Project3].[EmailConfirmed] = [Extent4].[EmailConfirmed]) AND ([Project3].[Online] = [Extent4].[Online]) AND ([Extent5].[ApplicationUserId] = [Project3].[Id])
) AS [Project5]) AS [C4]
FROM ( SELECT
[GroupBy1].[A1] AS [C1],
[GroupBy1].[A2] AS [C2],
[GroupBy1].[A3] AS [C3],
[GroupBy1].[K1] AS [Id],
[GroupBy1].[K2] AS [Online],
[GroupBy1].[K3] AS [Email],
[GroupBy1].[K4] AS [EmailConfirmed],
[GroupBy1].[K5] AS [UserName]
FROM ( SELECT
[Project2].[Id] AS [K1],
[Project2].[Online] AS [K2],
[Project2].[Email] AS [K3],
[Project2].[EmailConfirmed] AS [K4],
[Project2].[UserName] AS [K5],
MAX([Project2].[PriceInPLN]) AS [A1],
MAX([Project2].[PriceInPLN]) AS [A2],
MAX([Project2].[PriceInPLN]) AS [A3]
FROM ( SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Online] AS [Online],
[Extent1].[Email] AS [Email],
[Extent1].[EmailConfirmed] AS [EmailConfirmed],
[Extent1].[UserName] AS [UserName],
[Extent2].[PriceInPLN] AS [PriceInPLN],
[Extent2].[ApplicationUserId] AS [ApplicationUserId]
FROM [dbo].[AspNetUsers] AS [Extent1]
LEFT OUTER JOIN [dbo].[Bids] AS [Extent2] ON [Extent1].[Id] = [Extent2].[ApplicationUserId]
WHERE NOT EXISTS (SELECT
1 AS [C1]
FROM [dbo].[AspNetUserRoles] AS [Extent3]
WHERE ([Extent1].[Id] = [Extent3].[UserId]) AND ([Extent3].[RoleId] = #p__linq__0)
)
) AS [Project2]
GROUP BY [Project2].[Id], [Project2].[Online], [Project2].[Email], [Project2].[EmailConfirmed], [Project2].[UserName]
) AS [GroupBy1]
) AS [Project3] ) AS [Project6]
CROSS JOIN (SELECT
MAX([Extent7].[PriceInPLN]) AS [A1]
FROM [dbo].[Bids] AS [Extent7] ) AS [GroupBy3]
CROSS JOIN (SELECT
MAX([Extent8].[PriceInPLN]) AS [A1]
FROM [dbo].[Bids] AS [Extent8] ) AS [GroupBy4]
Can this be simplified?
Here is model of my my database generated by Entity Framework Power Tools:
I'm not sure why you modified your LINQ query so much from the original SQL query, but translating the SQL query closer to literally using the rules from my SQL to LINQ Recipe I get
var MaxPriceInPLN = db.Bids.Max(b => b.PriceInPLN);
var ans = from U in db.Users
where !U.Roles.Any(r => r.RoleId == adminRoleId)
join b in db.Bids on U.Id equals b.ApplicationUserId into bj
from b in bj.DefaultIfEmpty()
group new { U, b } by new { U.Id, U.UserName, U.Email } into Ubg
let maxBidPriceInPLN = Ubg.Max(Ub => Ub.b.PriceInPLN)
select new {
Ubg.Key.Id,
Ubg.Key.UserName,
Ubg.Key.Email,
PriceInPLN = maxBidPriceInPLN ?? 0,
BidsCount = Ubg.Count(Ub => Ub.b != null),
IsMax = maxBidPriceInPLN == MaxPriceInPLN
};
You can simplify the LINQ query by using the EF navigation properties to hide the join from your query:
var MaxPriceInPLN = db.Bids.Max(b => b.PriceInPLN);
var ans = from U in db.Users
where !U.Roles.Any(r => r.RoleId == adminRoleId)
let maxBidPriceInPLN = U.Bids.Max(b => b.PriceInPLN)
select new {
U.Id,
U.UserName,
U.Email,
PriceInPLN = maxBidPriceInPLN ?? 0,
BidsCount = U.Bids.Count(),
IsMax = maxBidPriceInPLN == MaxPriceInPLN
};

Entity Framework query with 2 many-to-many joins

I'm working on a project which is using EF Code first and has the following model relationships:
Item (Id, Name, virtual List<Category>, virtual List<Tag>)
Category (Id, Name, virtual List<Item>)
Tag (Id, Name, virtual List<Item>)
I'm running a search where I would like to get all items where the item name = searchTerm, the category id is contained in a list of ints and where the tag name exists in a list of tags.
public IEnumerable<Item> Search(string searchTerm, IEnumerable<int> categoryIds, IEnumerable<string> tags)
{
var query = (
from i in context.Items
from c in context.Categories
from t in context.Tags
where i.Name.Contains(searchTerm)
&& categoryIds.Contains(c.Id)
&& tags.Contains(t.Name)
select i);
return query.ToList();
}
In SQL the query would look like the following:
SELECT I.* FROM Items I
INNER JOIN ItemItemCategories IIC ON IIC.Item_Id = I.Id
INNER JOIN ItemCategories C ON C.Id = IIC.ItemCategory_Id
INNER JOIN ItemItemTags IIT ON IIT.Item_Id = I.Id
INNER JOIN ItemTags T On T.Id = IIT.ItemTag_Id
WHERE I.Question like '%sample%' -- searchTerm
AND C.Id in (1,2) -- categoryIds
AND (T.Text like '%Difficult%' OR T.Text like '%Technical%') -- tags
My question is how can I form my code to return the query above. This is the most efficient way to perform the query from my knowledge. Currently the following query is being run from code:
SELECT
[Filter1].[Id1] AS [Id],
[Filter1].[Name] AS [Name]
FROM (
SELECT
[Extent1].[Id] AS [Id1],
[Extent1].[Name] AS [Name]
FROM [dbo].[Items] AS [Extent1]
CROSS JOIN [dbo].[Categories] AS [Extent2]
WHERE [Extent2].[Id] IN (1, 2) ) AS [Filter1]
CROSS JOIN [dbo].[Tags] AS [Extent3]
WHERE ([Filter1].[Name] LIKE #p__linq__0 ESCAPE N'~') AND ([Extent3].[Name] IN (N'Difficult', N'Technical')) AND ([Extent3].[Name] IS NOT NULL)
Try this:
var query = ( from i in context.Items
from c in i.Categories
from t in i.Tags
where i.Name.Contains(searchTerm)
&& categoryIds.Contains(c.Id)
&& tags.Contains(t.Name)
select i).ToList();
You do not have to search through all the categories and tags elements, only those who are related with you Item.
About the query you want, IMHO I don't think there's a more efficient query in Linq to Entities to get the result you are expecting that the query I propose above. Look the sql code that is generated:
SELECT
[Filter1].[Id] AS [Id],
[Filter1].[Name] AS [Name]
FROM (SELECT [Extent1].[Id] AS [Id], [Extent1].[Name] AS [Name]
FROM [dbo].[Items] AS [Extent1]
INNER JOIN [dbo].[ItemCategories] AS [Extent2] ON [Extent1].[Id] = [Extent2].[Item_Id]
WHERE [Extent2].[Category_Id] IN (1, 2) ) AS [Filter1]
INNER JOIN (SELECT [Extent3].[Item_Id] AS [Item_Id]
FROM [dbo].[TagItems] AS [Extent3]
INNER JOIN [dbo].[Tags] AS [Extent4] ON [Extent4].[Id] = [Extent3].[Tag_Id]
WHERE ([Extent4].[Name] IN (N'Difficult', N'Technical')) AND ([Extent4].[Name] IS NOT NULL) ) AS [Filter2] ON [Filter1].[Id] = [Filter2].[Item_Id]
WHERE [Filter1].[Name] LIKE #p__linq__0 ESCAPE N'~'
As you can see it is quite similar with the query that you expect.

Entity Framework 6 too many joins

I have the following LINQ query:
var query = from a in c.ArticleSet
where a.GlobalAccess == false &&
a.Published == true &&
a.MagazineSet.IsPublished == true &&
a.MagazineSet.Press_Id == pressId &&
a.Tests.Id==a.Id &&
a.Tests.IsDeleted == false &&
a.Tests.IsPublished == true
orderby a.Id descending
select a.Id;
It tranforms to SQL like this:
ADO.NET:Execute Reader "SELECT
[Project1].[Id] AS [Id]
FROM ( SELECT
[Filter3].[Id1] AS [Id]
FROM (SELECT [Filter2].[Id1], [Filter2].[Magazine_Id1], [Filter2].[Press_Id1], [Filter2].[Press_Id2], [Filter2].[Press_Id3]
FROM (SELECT [Filter1].[Id1], [Filter1].[Magazine_Id1], [Extent5].[Press_Id] AS [Press_Id1], [Extent6].[Press_Id] AS [Press_Id2], [Extent7].[Press_Id] AS [Press_Id3]
FROM (SELECT [Extent1].[Id] AS [Id1], [Extent1].[Magazine_Id] AS [Magazine_Id1]
FROM [dbo].[ArticleSet] AS [Extent1]
INNER JOIN [dbo].[Tests] AS [Extent2] ON ([Extent1].[Id] = [Extent2].[Id]) AND ([Extent2].[Id] = [Extent1].[Id])
INNER JOIN [dbo].[MagazineSet] AS [Extent3] ON [Extent1].[Magazine_Id] = [Extent3].[Id]
WHERE (0 = [Extent1].[GlobalAccess]) AND (1 = [Extent1].[Published]) AND (1 = [Extent3].[IsPublished]) ) AS [Filter1]
INNER JOIN [dbo].[MagazineSet] AS [Extent4] ON [Filter1].[Magazine_Id1] = [Extent4].[Id]
LEFT OUTER JOIN [dbo].[MagazineSet] AS [Extent5] ON [Filter1].[Magazine_Id1] = [Extent5].[Id]
LEFT OUTER JOIN [dbo].[MagazineSet] AS [Extent6] ON [Filter1].[Magazine_Id1] = [Extent6].[Id]
LEFT OUTER JOIN [dbo].[MagazineSet] AS [Extent7] ON [Filter1].[Magazine_Id1] = [Extent7].[Id]
INNER JOIN [dbo].[Tests] AS [Extent8] ON [Filter1].[Id1] = [Extent8].[Id]
WHERE 0 = [Extent8].[IsDeleted] ) AS [Filter2]
INNER JOIN [dbo].[Tests] AS [Extent9] ON [Filter2].[Id1] = [Extent9].[Id]
INNER JOIN [dbo].[Tests] AS [Extent10] ON [Filter2].[Id1] = [Extent10].[Id]
WHERE 1 = [Extent10].[IsPublished] ) AS [Filter3]
INNER JOIN [dbo].[Tests] AS [Extent11] ON [Filter3].[Id1] = [Extent11].[Id]
WHERE (([Filter3].[Press_Id1] = #p__linq__0) AND ( NOT ([Filter3].[Press_Id2] IS NULL OR #p__linq__0 IS NULL))) OR (([Filter3].[Press_Id3] IS NULL) AND (#p__linq__0 IS NULL))
) AS [Project1]
ORDER BY [Project1].[Id] DESC"
The command text
"SELECT [Project1].[Id] AS [Id]
FROM ( SELECT
[Filter3].[Id1] AS [Id]
FROM (SELECT [Filter2].[Id1], [Filter2].[Magazine_Id1], [Filter2].[Press_Id1], [Filter2].[Press_Id2], [Filter2].[Press_Id3]
FROM (SELECT [Filter1].[Id1], [Filter1].[Magazine_Id1], [Extent5].[Press_Id] AS [Press_Id1], [Extent6].[Press_Id] AS [Press_Id2], [Extent7].[Press_Id] AS [Press_Id3]
FROM (SELECT [Extent1].[Id] AS [Id1], [Extent1].[Magazine_Id] AS [Magazine_Id1]
FROM [dbo].[ArticleSet] AS [Extent1]
INNER JOIN [dbo].[Tests] AS [Extent2] ON ([Extent1].[Id] = [Extent2].[Id]) AND ([Extent2].[Id] = [Extent1].[Id])
INNER JOIN [dbo].[MagazineSet] AS [Extent3] ON [Extent1].[Magazine_Id] = [Extent3].[Id]
WHERE (0 = [Extent1].[GlobalAccess]) AND (1 = [Extent1].[Published]) AND (1 = [Extent3].[IsPublished]) ) AS [Filter1]
INNER JOIN [dbo].[MagazineSet] AS [Extent4] ON [Filter1].[Magazine_Id1] = [Extent4].[Id]
LEFT OUTER JOIN [dbo].[MagazineSet] AS [Extent5] ON [Filter1].[Magazine_Id1] = [Extent5].[Id]
LEFT OUTER JOIN [dbo].[MagazineSet] AS [Extent6] ON [Filter1].[Magazine_Id1] = [Extent6].[Id]
LEFT OUTER JOIN [dbo].[MagazineSet] AS [Extent7] ON [Filter1].[Magazine_Id1] = [Extent7].[Id]
INNER JOIN [dbo].[Tests] AS [Extent8] ON [Filter1].[Id1] = [Extent8].[Id]
WHERE 0 = [Extent8].[IsDeleted] ) AS [Filter2]
INNER JOIN [dbo].[Tests] AS [Extent9] ON [Filter2].[Id1] = [Extent9].[Id]
INNER JOIN [dbo].[Tests] AS [Extent10] ON [Filter2].[Id1] = [Extent10].[Id]
WHERE 1 = [Extent10].[IsPublished] ) AS [Filter3]
INNER JOIN [dbo].[Tests] AS [Extent11] ON [Filter3].[Id1] = [Extent11].[Id]
WHERE (([Filter3].[Press_Id1] = #p__linq__0) AND ( NOT ([Filter3].[Press_Id2] IS NULL OR #p__linq__0 IS NULL))) OR (([Filter3].[Press_Id3] IS NULL) AND (#p__linq__0 IS NULL))
) AS [Project1]
ORDER BY [Project1].[Id] DESC
I think 3 join is enough in this example.
Why does Entity framework create such huge query?
Your linq query is fine, other than the fact that it references a lot of tables at once. If this is really what you want, there there is nothing to be afraid of. It's only not "super efficient" because you are referencing 3 tables at once.
Just remember that the sql query that EF produces is machine-created. It's not always the best, but it should alway be perfectly valid. I'm not sure why it chose this form over another, but if it works, why worry?
I always suggest that people limit their queries to only the referencing tables they need. As the system grows, the processing time will increase as well, and with this many table joins, it might start to get more noticeable.

How to write linq query to prevent duplicates joins?

I have a query that search for all accommodations in an order, sorted by day. When I check on the sever what query is executed, I see multiple join toward the same table on the same keys
var parcourt = this.DataService.From<OrderItem>()
.Where(i => i.OrderId == orderId && i.Product.ProductTypeId == (int)ProductTypes.Accommodation)
.OrderBy(i => i.DayNumber)
.ThenBy(i => i.OrderItemId)
.Select(i => new
{
i.OrderItemId,
i.DayNumber,
i.Product.Establishment.Address,
i.Product.Establishment.Coordinates
});
If you check the resulting SQL (as show by ToTraceString), you can see two join on the Products and Establishments table.
SELECT
[Project1].[OrderItemId] AS [OrderItemId],
[Project1].[DayNumber] AS [DayNumber],
[Project1].[Address] AS [Address],
[Project1].[EstablishmentId] AS [EstablishmentId],
[Project1].[Latitude] AS [Latitude],
[Project1].[Longitude] AS [Longitude]
FROM ( SELECT
[Extent1].[OrderItemId] AS [OrderItemId],
[Extent1].[DayNumber] AS [DayNumber],
[Extent4].[Address] AS [Address],
[Extent5].[EstablishmentId] AS [EstablishmentId],
[Extent5].[Latitude] AS [Latitude],
[Extent5].[Longitude] AS [Longitude]
FROM [dbo].[OrderItems] AS [Extent1]
INNER JOIN [dbo].[Products] AS [Extent2] ON [Extent1].[ProductId] = [Extent2].[ProductId]
LEFT OUTER JOIN [dbo].[Products] AS [Extent3] ON [Extent1].[ProductId] = [Extent3].[ProductId]
LEFT OUTER JOIN [dbo].[Establishments] AS [Extent4] ON [Extent3].[EstablishmentId] = [Extent4].[EstablishmentId]
LEFT OUTER JOIN [dbo].[Establishments] AS [Extent5] ON [Extent3].[EstablishmentId] = [Extent5].[EstablishmentId]
WHERE (1 = [Extent2].[ProductTypeId]) AND ([Extent1].[OrderId] = #p__linq__0)
) AS [Project1]
ORDER BY [Project1].[DayNumber] ASC, [Project1].[OrderItemId] ASC
How can I prevent this linq-to-entities from joining twice on a table? How can I rewrite the query to avoid this situation?
The table structure goes as follow (simplified):
This is the query
Could you try this query? I think if you call all your joins explicitly, it'll not create joins automatically.
var parcourt = (from i in this.DataService.OrderItem
join p in this.DataService.Product on p.ProductId equals i.ProductId
join e in this.DataService.Establishments on e.EstablishmentId equals p.EstablishmentId
where i.OrderId == orderId && p.ProductTypeId == (int)ProductTypes.Accomodation
orderby i.DayNumber, i.OrderItemId
select new
{
i.OrderItemId,
i.DayNumber,
e.Address,
e.Coordinates
});

Categories

Resources