我查看了一些相关的问题,但没有看到任何与我需要的相符的东西,所以请耐心等待。
我有三个层次结构的类:
public class Dialog {
public DateTime CreatedOn { get; set; }
}
public class Response {
public DateTime CreatedOn { get; set; }
public IList<Dialog> Dialogs { get; set; }
}
public class Request{
public DateTime CreatedOn { get; set; }
public IList<Response> Responses { get; set; }
}
所以基本上,我正在显示请求,但我想按最近活动的顺序显示它们,无论是在消息,响应还是对话框上。显然,某些消息可能没有响应,而某些响应可能没有对话框。
我正在使用EntityFramework,但这并不一定相关,因为这个排序可以在任何使用LINQ来排序对象的分层分组上。
这是我到目前为止所做的事情:
Requests.OrderByDescending(r => r.CreatedOn)
.ThenByDescending(r => r.Offers.Any() ? r.Offers.Max(o => o.CreatedOn) : DateTime.MinValue)
.ThenByDescending(r => r.Offers.SelectMany(o => o.Dialogs).Any() ? r.Offers.SelectMany(o => o.Dialogs).Max(d => d.CreatedOn) : DateTime.MinValue)
我的问题是,我认为随后的ThenByDescending
不会覆盖前一个,或者我是否以错误的方式思考这个问题?有没有办法在请求及其所有后代之间的一个订购中找到Max CreatedOn?
答案 0 :(得分:1)
您可以获取每个列表的最大日期,然后获取tem的最大(最大?)日期,而不是进行多次排序(正如您所说的会破坏之前的排序)。
如果您至少保证有空的Response
和Dialogs
列表,则可以获得这样的最长日期:
var r = req.OrderByDescending(x => new[]
{
x.CreatedOn,
x.Responses.Select(y => y.CreatedOn).Max(),
x.Responses.Select(y => y.Dialogs.Select(z => z.CreatedOn).Max()).Max()
}.Max()).Select(x => x).ToList();
如果值可以为null,则可以在查询中创建新列表。如果您直接将此信息提供给EF来查询数据库,它可能无效......我现在无法在任何地方进行测试。
var r = req.OrderByDescending(x => new[]
{
x.CreatedOn,
(x.Responses ?? new List<Response>()).Select(y => y.CreatedOn).Max(),
(x.Responses ?? new List<Response>()).Select(y => (y.Dialogs ?? new List<Dialog>())
.Select(z => z.CreatedOn).Max()).Max()
}.Max()).Select(x => x).ToList();
OP编辑
我必须做一些修改才能编译。正如基于这个答案的那样,感谢Grant Winney。
var results = req.OrderByDescending(r => new[] { // Create a new array to hold the dates.
r.CreatedOn, // Start with the date of the Request
(r.Offers.Any() ?
r.Offers.Select(o => o.CreatedOn).Max() : // If the Request has any Offers, get the max date of the offers.
DateTime.MinValue), // Otherwise add Min value so it won't affect the results.
(r.Offers.Any() ?
r.Offers.Select(o => o.Dialogs.Any() ? // If each Offer from each Request have any Dialogs
o.Dialogs.Select(d => d.CreatedOn).Max() : // Get the Max Dialog Date for each Offer
DateTime.MinValue) // Or put in a Min value for each Offer.
.Max() : // Then find the max for reach Offer's Dialogs (or Min Value for each Offer)
DateTime.MinValue) // If there are no Offers, again use Min value.
}.Max()) // Then get the Max from the 3 values in the array.
.Select(x => x).ToList();
答案 1 :(得分:1)
如果你不介意改变你的模型,也许你可以这样做:
public class Dialog {
public DateTime CreatedOn { get; set; }
}
public class Response {
public DateTime CreatedOn { get; set; }
public IList<Dialog> Dialogs { get; set; }
public DateTime MaxDateTime {
get {
if (Dialogs == null) return CreatedOn;
var max = Dialogs.Max(o => o.CreatedOn);
return CreatedOn >= max ? CreatedOn : max;
}
}
}
public class Request{
public DateTime CreatedOn { get; set; }
public IList<Response> Responses { get; set; }
public DateTime MaxDateTime {
get {
if (Responses == null) return CreatedOn;
var max = Responses.Max(o => o.MaxDateTime);
return CreatedOn >= max ? CreatedOn : max;
}
}
}
然后,您只需对MaxDateTime
属性进行排序即可进行排序。
var orderedRequests = requests.OrderByDescending(o => o.MaxDateTime);