3

我有以下

IList<Project> projects = (from update in dbContext.TicketUpdates
               where update.TicketUpdatesEmployeeID == Profile.EmployeeID
               orderby update.TicketUpdatesEndDate descending
               select update.Ticket.Project).Distinct().ToList();

我知道这Distinct()不能保证订单,但我不能在之后重新排序,因为投影丢失了我用来订购的字段。我该如何解决这个问题?

4

3 回答 3

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)

有一个采用自定义 IEqualityComparer 的 Distinct 重载因此,在投影数据之前,请使用自定义 IEqualityComparer 对 TicketUpdates 进行 Distinct 。

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();
    }

}
于 2012-09-18T15:37:08.717 回答
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);

通过使用GroupByuu.Ticket.Project每个更新将按其关联的项目进行分组。如果您有 10 个项目和 30 个更新分布在其中,那么在该阶段的输出中您将有 10 个组(每个项目一个)。接下来,我们按组的最新结束日期对组进行排序,这会保留您要查找的降序。最后,我们从每个IGrouping项目中选择密钥。

于 2012-09-18T15:37:44.433 回答
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;
于 2012-09-18T15:47:11.437 回答