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
Update を使用した新しいソリューション: 実際には、はるかに簡単なソリューションがあります。

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

各更新で使用すると、関連するプロジェクトによってグループ化されGroupByます。uu.Ticket.Project10 個のプロジェクトがあり、それらの間に 30 個の更新が分散している場合、そのステージの出力には 10 個のグループ (プロジェクトごとに 1 つ) があります。次に、グループを最新の終了日で並べ替えます。これにより、探していた降順が維持されます。最後にIGrouping、プロジェクトであるそれぞれからキーを選択します。

于 2012-09-18T15:37:44.433 に答える
0

GroupBy 演算子を使用して一意のレコードを取得し、新しいレコードセットで order by を実行できます。

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 に答える