正确的LINQ语法,根据集合中的值对Ienumerable排序
本文关键字:Ienumerable 排序 集合 LINQ 语法 | 更新日期: 2023-09-27 17:52:48
我有以下类/表:
public class Shift
{
public int ShiftID { get; set; }
public DateTime ShiftDate { get; set; }
public int DepartmentID { get; set; }
//other irrelevant stuff...
public virtual ICollection<ShiftMission> ShiftMission { get; set; }
}
和
public class ShiftMission
{
public int ShiftMissionID { get; set; }
public TimeSpan StartTime { get; set; }
public int ShiftID { get; set; }
//more irrelevant things
}
在班次的索引视图中,我需要将列表按DepartmentID排序,然后按ShiftDate排序,最后按班次任务集合中最早/第一个任务的开始时间排序。真正让我困住的是分班任务。
我已经试过了,但是它告诉我没有列移位日期,也没有列departmentd:
var allShifts = _context.Shifts
.Include(s => s.Department)
.Include(s => s.ShiftMission).ThenInclude(sm => sm.Activity)
.OrderBy(s => s.DepartmentID)
.ThenBy(s => s.ShiftDate)
.ThenBy(s => s.ShiftMission.OrderBy(sm => sm.StartTime).Select(sm => sm).FirstOrDefault());
return View(allShifts.ToList());
我还尝试将班次选择到一个新组中,但这让我感到困惑,并导致更多的异常,并将DepartmentA排序在DepartmentB下面
var allShifts = _context.Shifts
.Include(s => s.Department)
.Include(s => s.ShiftMission).ThenInclude(sm => sm.Activity)
.GroupBy(s => s.DepartmentID)
.Select(group => new {Shifts = group.OrderBy(x => x.ShiftDate).ThenBy(x => x.ShiftMission.OrderBy(sm => sm.StartTime).First())})
.SelectMany(group => group.Shifts);
实现这一点的正确方法是什么?我做的每一个变化都让我更加困惑。
您希望按三个值对移位进行排序:
- DepartmentId,
- ShiftDate,
- Shift任务中所有StarTimes的最小StartTime。ShiftMissions
要在将在一个SQL查询中执行的一个查询中执行此操作,您可以加入DbSet _context。shift和_context。ShiftMissions on equal shiftId.
连接的结果可以按照您想要的方式排序:
var joinQuery = _context.Shifts.Join(_context.ShiftMissions, // join table Shifts and table ShiftMissions
shift => shift.ShiftId, // from the Shifts, take ShiftId
shiftMission => shiftMission.ShiftId, // from the ShiftMisions taks ShiftId
(shift, shiftMission) => // for all shifts and shiftMissions with equal shiftId take
new {
DepartmendId = shift.DepartmentId,
ShiftDate = shift.ShiftDate,
StartTime = shiftMission.StartTime,
ShiftToSort = shift,
});
注意,查询不会被执行。
如果您执行查询,您将看到您已经创建了一个表,其中包含包含DepartmentId, ShiftDate, StartTime和ShiftToSort的记录,其中包含原始的Shift,其中提取了要排序的三个属性。
现在,如果你把它们按正确的顺序排序,你会得到正确顺序的项目:
var orderedQuery = joinQuery
.OrderBy(item => item..DepartmentId)
.ThenBy(item => item.ShiftDate)
.ThenBy(item => item.StartTime)
这个查询将导致太多的ShiftToSort:对于每个ShiftMission,匿名集合将有一个ShiftToSort
您只需要属性ShiftToSort的不同值
var shiftToSortQuery = orderedQuery
.Select(item => item.ShiftToSort)
.Distinct();
注意,查询仍然没有执行!
var orderedList = finalQuery.ToList();
当然你可以用一条语句来写:
var orderedList = _context.Shifts.Join(_context.ShiftMissions, // join table
...
.Distinct()
.ToList();
如果您调查使用include时执行的SQL语句,您将看到include语句被转换为SQL连接。
var sortedQuery1 = _context.Shifts
.OrderBy(shift => shift.DepartmentId)
.ThenBy(shift => shift.ShiftDate);
结果必须按shift中所有ShiftMission项的最小StartTime排序)。因此,对于sortedQuery1中的每个元素,您需要计算ShiftMissions数组中的最小startTime。这是:
var sortedQuery2 = sortedQuery1
.Orderby(itemSortedByDeparmentIdAndShiftDate =>
// What value must be used to sort this item?
// Answer: The minimum StartTime of all times in ShiftMissions
// so for each item calculate the minimum Starttime:
itemSortedByDepartmentIdAndShiftDate.ShiftMissions
.Min(shiftMission => shiftMission.StartTime);
如果你使用你的数据库分析器,你会看到一个类似的连接和排序是完成的,也是完全在SQL中,因此非常有效