我有一份报告清单,每份报告都有一些“网络”。这些“网队”中的每一个都有一个状态,我想根据他们可能拥有的状态重新排序这些报告。我正在错误地编写LINQ表达式,因为我的OrderBy()括号中的内容不是可订购的实际单个字段。这是它的外观:
reports.OrderBy(r => r.Nets.Where(n => n.NetStatus.Equals("New")).OrderBy(n => n.NetId))
.ThenBy(r => r.Nets.Where(n => n.NetStatus.Equals("Updated")).OrderBy(n => n.NetId))
.ThenBy(r => r.Nets.Where(n => n.NetStatus.Equals("Ignored")).OrderBy(n => n.NetId))
因为它不是OrderBy和ThenBy子句中的实际可订购字段,所以会抛出一个错误,说“DbSortClause表达式必须具有类似于命令的类型参数Name:Key”,这显然是有道理的。我无法弄清楚的是如何正确地传达我正在尝试订购的内容,如第一段所述。
答案 0 :(得分:1)
您可以尝试将顶层Linq语句分解为foreach
,并为您拥有的每种NetStatus
类型创建一个列表。然后,您可以将列表组合成订购结果。
foreach (var r in reports)
{
var newList = r.Nets.Where(n => n.NetStatus.Equals("New")).OrderBy(n => n.NetId).ToList();
var upatedList = r.Nets.Where(n => n.NetStatus.Equals("Updated")).OrderBy(n => n.NetId).ToList();
var IgnoredList = r.Nets.Where(n => n.NetStatus.Equals("Ignored")).OrderBy(n => n.NetId).ToList();
var result = newList.Concat(upatedList).Concat(IgnoredList);
}
建立上述代码;按Reports
的顺序对Reports
进行排序,其中包含至少1个'新' NetStatus,然后Reports
包含至少1 Updated
个NetStatus,然后是剩余的Reports
,我们可以根据每个r
对象将每个Status List
对象添加到一个独立的列表中我们在上面创建的 var sortedReports = new List<Report>();
foreach (var r in reports)
{
var newList = r.Nets.Where(n => n.NetStatus.Equals("New")).OrderBy(n => n.NetId).ToList();
var upatedList = r.Nets.Where(n => n.NetStatus.Equals("Updated")).OrderBy(n => n.NetId).ToList();
var IgnoredList = r.Nets.Where(n => n.NetStatus.Equals("Ignored")).OrderBy(n => n.NetId).ToList();
if (newList.Count > 0)
{
sortedReports.Add(r);
}
else if (upatedList.Count > 0)
{
sortedReports.Add(r);
}
else
{
sortedReports.Add(r);
}
}
类型:
cv2.aruco
答案 1 :(得分:1)
netStatusList
列表(这是为了帮助您进行自定义排序)。按netStatusList
中的每个净状态索引排序,然后按网络ID排序。
List<String> netStatusList= new List<String> { "New", "Updated", "Ignored" };
reports.SelectMany(r => r.Nets).ToList().OrderBy(n => netStatusList.IndexOf(n.NetStatus))
.ThenBy(n => n.NetId);
答案 2 :(得分:1)
根据your comment关于当前答案之一(这应该是问题的一部分):
更像是,报告至少有一个状态为&#34; New&#34;,先排序。然后&#34;更新&#34;,然后&#34;忽略&#34;。现在关于所有报告如何与&#34; New&#34;应该分类,它真的不重要;也许按他们的报告排序。
您正在寻找某种优先顺序。
要实现这一点,您可以使用条件表达式(如
)为每个状态分配优先级status == "New" ? 1 :
status == "Updated" ? 2 :
status == "Ignored" ? 3 : 4
应转换为SQL CASE WHEN ... THEN ... WHEN ... THEN ... ELSE .. END
表达式。
此外,由于您可能具有多种状态,因此您可以使用Min
函数来确定主记录的优先级,然后将其用于排序。
付诸行动(DefaultIfEmpty()
将处理空r.Nets
):
var query = reports
.OrderBy(r => r.Nets.DefaultIfEmpty().Min(n =>
n.NetStatus == "New" ? 1 :
n.NetStatus == "Updated" ? 2 :
n.NetStatus == "Ignored" ? 3 :
4))
.ThenBy(r => r.ReportId);
或者如果查询提供程序不处理透明的null
记录(如EF提供程序那样):
var query = reports
.OrderBy(r => r.Nets.Select(n => n.NetStatus).DefaultIfEmpty().Min(status =>
status == "New" ? 1 :
status == "Updated" ? 2 :
status == "Ignored" ? 3 :
4))
.ThenBy(r => r.ReportId);
无论哪种方式都有效并且翻译得更好。
答案 3 :(得分:0)
如果您的目标是获得每个报告的网队
reports.SelectMany(r => r.Nets).GroupBy(e=> e.NetStatus).Select(e=> new
{
Key = e.Key,
List = e.OrderBy(e=> e.NetId)
});
然而,如果你是报告,那么你可以
reports.Select(report => new
{
Report = report,
Nets = report.Nets.GroupBy(e=> e.NetStatus).Select(e=> new {
Key = e.Key,
List = e.OrderBy(e=> e.NetId)
});
});
答案 4 :(得分:-1)
我认为您可能误解了OrderBy的工作方式。您没有提供首先要订购的商品,而是提供value
订购。因此,在您的情况下,您希望在NetStatus
上订购,但是,如果您刚刚reports.OrderBy(r => r.NetStatus)
,则会在NetStatus上按字母顺序排序。
相反,您需要根据实际需要排序的顺序返回一个正确排序的值。考虑这样的事情:
reports.OrderBy(r => {
switch(r.NetStatus){
case "New": return 1;
case "Updated": return 2;
case "Ignored": return 3;
}
})
现在,您在NetStatus
的值上返回值1,2或3 基于,但是,1,2和3将正确排序。
然后,您可以使用.ThenBy(n => n.NetId)
对其进行跟进,以便按NetStatus字段排序后的NetId
字段进行排序。
编辑:IvanStoev在下面指出NetStatus实际上是Net集合中的一个属性,而不是直接报告。您可能需要调整我的示例以进行补偿,但希望它可以解决这个问题。您需要为OrderBy提供单个单独值以进行排序,而不是值集合。
完整示例:
class Program {
static void Main(string[] args) {
List<Report> reports = new List<Report>();
reports.Add(new Report() { NetStatus = "Updated", NetId = 1 });
reports.Add(new Report() { NetStatus = "New", NetId = 2 });
reports.Add(new Report() { NetStatus = "Ignored", NetId = 4 });
reports.Add(new Report() { NetStatus = "Ignored", NetId = 3 });
var orderedReports = reports.OrderBy((r) => {
switch (r.NetStatus) {
case "New": return 1;
case "Updated": return 2;
case "Ignored": return 3;
default: return 0;
}
}).ThenBy(r => r.NetId);
foreach (var report in orderedReports) {
Console.WriteLine($"{report.NetId} {report.NetStatus}");
}
Console.ReadLine();
}
}
public class Report {
public String NetStatus { get; set; }
public int NetId { get; set; }
}
输出
2 New
1 Updated
3 Ignored
4 Ignored