我有以下
IList<Project> projects = (from update in dbContext.TicketUpdates
where update.TicketUpdatesEmployeeID == Profile.EmployeeID
orderby update.TicketUpdatesEndDate descending
select update.Ticket.Project).Distinct().ToList();
我知道Distinct()
并不保证订单,但之后我无法对其进行重新排序,因为投影会丢失我用来订购的字段。我该如何解决这个问题?
答案 0 :(得分:1)
使用GroupBy的新解决方案
更新的
实际上有一个更简单的解决方案:
IList<Project> projects = (from update in dbContext.TicketUpdates where update.TicketUpdatesEmployeeID == Profile.EmployeeID)
.GroupBy(tu=>tu.Ticket.Project)
.Select(group=>group.First())
.OrderByDescending(tu=>tu.TicketUpdatesEndDate)
.Select(tu=>tu.Ticket.Project)
.ToList();
(我刚看到这篇文章时,其他人也发了类似的答案)
使用自定义IEqualityComparer的旧解决方案(我不确定这是否适用于linq2sql)
有一个Distinct overload that takes a custom IEqualityComparer。因此,在投影数据之前,使用自定义IEqualityComparer 对TicketUpdates进行区分。
如果IEqualityComparer具有相同的项目,则它应将所有TicketUpdates统计为相等。这样,具有相同项目的TicketUpdates将被丢弃。
(请注意,您不会控制哪个具有相同项目的TicketUpdates将被丢弃。因此,如果这些具有相同项目的TicketUpdates具有不同的EndDates,则需要一个涉及GroupBy的解决方案。
IList<Project> projects = (from update in dbContext.TicketUpdates where update.TicketUpdatesEmployeeID == Profile.EmployeeID)
.Distinct(new ProjectComparer())
.OrderByDescending(tu=>tu.TicketUpdatesEndDate)
.Select(tu=>tu.Ticket.Project)
.ToList();
// Your comparer should look somewhat like this
// (untested code! And I do not know all the details about your class structure)
class ProjectComparer : IEqualityComparer<TicketUpdates>
{
// Products are equal if their names and product numbers are equal.
public bool Equals(TicketUpdates x, TicketUpdates y)
{
//Check whether the compared objects reference the same data.
if (Object.ReferenceEquals(x, y)) return true;
//Check whether any of the compared objects is null.
if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
return false;
//Check whether projects are equal.
//(perhaps do a null check for Ticket!)
return x.Ticket.Project== y.Ticket.Project;
}
// If Equals() returns true for a pair of objects
// then GetHashCode() must return the same value for these objects.
public int GetHashCode(TicketUpdates x)
{
//Check whether the object is null
if (Object.ReferenceEquals(x, null)) return 0;
// null check for Ticket and Project?
return x.Ticket.Project.GetHashCode();
}
}
答案 1 :(得分:1)
我认为最好的办法是发布流程以保持订购:
var projects = (from update in dbContext.TicketUpdates
where update.TicketUpdatesEmployeeID == Profile.EmployeeID
orderby update.TicketUpdatesEndDate descending
select update.Ticket.Project);
var seen = new HashSet<Project>();
foreach (var project in projects)
{
if (seen.Add(project))
{
// A distinct project
}
}
或者你可以滥用 GroupBy
:
var projects = dbContext.TicketUpdates
.Where(uu => uu.TicketUpdatesEmployeeID == Profile.EmployeeID)
.GroupBy(uu => uu.Ticket.Project)
.OrderByDescending(gg => gg.Max(uu => uu.TicketUpdatesEndDate))
.Select(gg => gg.Key);
在GroupBy
之间使用uu.Ticket.Project
,每个更新都会按其关联的项目进行分组。如果你有10个项目和30个更新,那么你将在该阶段的输出中有10个组 - 每个项目一个。接下来,我们按照最新的结束日期对组进行排序,保留您要查找的降序。最后,我们从项目的每个IGrouping
中选择密钥。
答案 2 :(得分:0)
您可以使用GroupBy运算符获取唯一记录,然后在新记录集上执行订单。
var projectList = dbContext.TicketUpdates.GroupBy(p => p.TicketUpdatesEmployeeId)
.Where( r => r.TicketUpdatesEmployeeId == Profile.EmployeeId)
.Select(r => r.First())
.OrderByDesc(q => q.TicketUpdatesEndDate)
.Select(n => n.First()).Ticket.Project;