[英]Using .Where() clause inside an .Include() on a linq query with multiples includes
[英]LINQ query dropping includes when adding `.Contains()` in where clause
我有一個有點復雜的查詢,我試圖在 Linq(EntityFramework Core 2.1)中構建,我遇到了我無法理解的行為。 以下查詢運行良好且看似高效:
var q = ( from n in TaskUpdates.Include(t => t.Status).Include("Task").Include("Task.Requirement").Include("User").Include("User.Employee") where n.User.Employee.EmployeeNumber == 765448466 group n by n.UpdateDate into tu select tu.OrderByDescending(t=>t.UpdateDate).FirstOrDefault() ) .Select(x => x.Task.Requirement);
這可以按我的預期工作,執行我想要的所有連接,並在SELECT
子句中包含預期的字段:
SELECT [t].[TaskUpdateID], [t].[Active], [t].[TaskId], [t].[Notes], [t].[StatusId], [t].[UpdateDate], [t].[UserId], [t.Task].[TaskID], [t.Task].[Active], [t.Task].[CreatedDate], [t.Task].[RequirementId], [t.Task].[UserId], [t.Task.Requirement].[RequirementID], [t.Task.Requirement].[Active], [t.Task.Requirement].[Description], [t.Task.Requirement].[Hours], [t.Task.Requirement].[Link], [t.Task.Requirement].[Name], [t.Task.Requirement].[RequirementTypeId], [t.Task.Requirement].[ExternalId], [t.Task.Requirement].[SortOrder], [t.Status].[StatusId], [t.Status].[Active], [t.Status].[IsComplete], [t.Status].[Title], [t.User].[UserId], [t.User].[Active], [t.User].[Created], [t.User].[EmployeeNumber], [t.User].[LastLogin], [t.User].[LastUpdated], [t.User.Employee].[EMPLOYEENUMBER], [t.User.Employee].[BEGINDATE], [t.User.Employee].[CITY], [t.User.Employee].[EMPLOYEETYPE], [t.User.Employee].[ENDDATE], [t.User.Employee].[FIRST_NAME], [t.User.Employee].[GENERATION_SUFFIX], [t.User.Employee].[STATUS], [t.User.Employee].[LAST_NAME], [t.User.Employee].[MIDDLE_NAME], [t.User.Employee].[MOBILE], [t.User.Employee].[ORGCODE], [t.User.Employee].[PHONE_NUMBER], [t.User.Employee].[PRIMARYEMAIL], [t.User.Employee].[STATE], [t.User.Employee].[STREET], [t.User.Employee].[TITLE], [t.User.Employee].[ZIPCODE], [t.User.Employee].[BUILDING], [t.User.Employee].[ROOM]
FROM [TaskUpdates] AS [t]
INNER JOIN [Tasks] AS [t.Task] ON [t].[TaskId] = [t.Task].[TaskID]
LEFT JOIN [Requirements] AS [t.Task.Requirement] ON [t.Task].[RequirementId] = [t.Task.Requirement].[RequirementID]
INNER JOIN [Status] AS [t.Status] ON [t].[StatusId] = [t.Status].[StatusId]
INNER JOIN [Users] AS [t.User] ON [t].[UserId] = [t.User].[UserId]
INNER JOIN [DirectoryPeople] AS [t.User.Employee] ON [t.User].[EmployeeNumber] = [t.User.Employee].[EMPLOYEENUMBER]
WHERE [t.User.Employee].[EMPLOYEENUMBER] = 765448466
ORDER BY [t].[UpdateDate]
GO
(我正在使用 LINQPad 來試驗這個查詢並獲得 SQL。)特別是,結尾的.Select(...)
方法正確地從查詢中返回了Requirement
object。
讓我感到困惑的是,如果我想讓這個查詢返回多個員工的數據,並且我像這樣更改where
子句:
var employeeNumbers = new int[] { 765448466 }; var q = ( from n in TaskUpdates.Include(t => t.Status).Include("Task").Include("Task.Requirement").Include("User").Include("User.Employee") //where n.User.Employee.EmployeeNumber == 765448466 where employeeNumbers.Contains(n.User.Employee.EmployeeNumber) group n by n.UpdateDate into tu select tu.OrderByDescending(t=>t.UpdateDate).FirstOrDefault() ) .Select(x => x.Task.Requirement);
這完全按照我的預期更改了生成的 SQL WHERE
子句,但它現在完全忽略了from
子句中的Include
:
SELECT [t].[TaskUpdateID], [t].[Active], [t].[TaskId], [t].[Notes], [t].[StatusId], [t].[UpdateDate], [t].[UserId]
FROM [TaskUpdates] AS [t]
INNER JOIN [Users] AS [t.User] ON [t].[UserId] = [t.User].[UserId]
INNER JOIN [DirectoryPeople] AS [t.User.Employee] ON [t.User].[EmployeeNumber] = [t.User.Employee].[EMPLOYEENUMBER]
WHERE [t.User.Employee].[EMPLOYEENUMBER] IN (765448466)
ORDER BY [t].[UpdateDate]
GO
(僅在執行where
時需要加入),最終.Select(...)
的結果現在返回null
。
這是已知的行為,有或沒有解釋嗎? 我是否錯誤地使用了Include
指令,或者是否有更好的方法/位置讓他們使用 go 來解決這個問題?
我不能確定原因,我懷疑 EF 正在使用包含的不同翻譯路徑並且缺少包含,但是正如您所看到的,它根本沒有翻譯 GroupBy,所以它絕對可以重新設計以匹配更多的EF風格。
TaskUpdates
.Include(x => x.Task)
.ThenInclude(x => x.Requirement)
.Where(x => employeeNumbers.Contains(x.User.Employee.EmployeeNumber))
.ToList()
.GroupBy(x => x.UpdateDate)
.Select(x => new {
UpdateDate = x.Key,
FirstRequirement = x.First().Task.Requirement
})
.ToList();
This should translate the statements before the first ToList into SQL, populate the results in-memory and allow C# to do the groupby and aggregates on the whole object which SQL would be unable to do.
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.