C# 如何在嵌套表字段上使用linq OrderBy?
我有一份报告清单,每份报告都有一些“网络”。每个“网络”都有一个状态,我想根据它们可能具有的状态对这些报告重新排序。我写的LINQ表达式不正确,因为OrderBy()括号中的内容不是一个实际的可排序字段。下面是它的外观:C# 如何在嵌套表字段上使用linq OrderBy?,c#,.net,linq,linq-to-sql,sql-order-by,C#,.net,Linq,Linq To Sql,Sql Order By,我有一份报告清单,每份报告都有一些“网络”。每个“网络”都有一个状态,我想根据它们可能具有的状态对这些报告重新排序。我写的LINQ表达式不正确,因为OrderBy()括号中的内容不是一个实际的可排序字段。下面是它的外观: reports.OrderBy(r => r.Nets.Where(n => n.NetStatus.Equals("New")).OrderBy(n => n.NetId)) .ThenBy(r => r.Nets.Where(n =>
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的类型”,这很有道理。我无法理解的是,如何正确地传达我在第一段中所说的订购内容。我想您可能误解了OrderBy的工作原理。您不提供要先订购的项目,而是提供一个要订购的
值。因此,在您的情况下,您希望在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实际上是网络集合上的一个属性,而不是直接报告。您可能需要调整我的示例以进行补偿,但希望它能让您理解我的想法。您需要为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; }
}
我想你可能误解了OrderBy的工作原理。您不提供要先订购的项目,而是提供一个要订购的值。因此,在您的情况下,您希望在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实际上是网络集合上的一个属性,而不是直接报告。您可能需要调整我的示例以进行补偿,但希望它能让您理解我的想法。您需要为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; }
}
您可以尝试将顶层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);
}
根据上述规范建造;要按照包含至少1个“新”NetStatus的报告
的顺序对报告
进行排序,然后是包含至少1个更新的NetStatus的报告
,然后是剩余的报告
,我们可以根据上面创建的每种类型的状态列表的计数,将每个r
对象添加到独立列表中:
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);
}
}
var sortedReports=new List();
foreach(报告中的var r)
{
var newList=r.Nets.Where(n=>n.NetStatus.Equals(“New”)).OrderBy(n=>n.NetId.ToList();
var upatedList=r.Nets.Where(n=>n.NetStatus.Equals(“更新”)).OrderBy(n=>n.NetId.ToList();
var IgnoredList=r.Nets.Where(n=>n.NetStatus.Equals(“忽略”)).OrderBy(n=>n.NetId.ToList();
如果(newList.Count>0)
{
分拣报告。添加(r);
}
如果(upatedList.Count>0),则为else
{
分拣报告。添加(r);
}
其他的
{
分拣报告。添加(r);
}
}
您可以尝试将顶层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);
}
根据上述规范建造;要按照包含至少1个“新”NetStatus的报告
的顺序对报告
进行排序,然后是包含至少1个更新的NetStatus的报告
,然后是剩余的报告
,我们可以根据上面创建的每种类型的状态列表的计数,将每个r
对象添加到独立列表中:
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);
}
}
var sortedReports=new List();
foreach(报告中的var r)
{
var newList=r.Nets.Where(n=>n.NetStatus.Equals(“New”)).OrderBy(n=>n.NetId.ToList();
var upatedList=r.Nets.Where(n=>n.NetStatus.Equals(“更新”)).OrderBy(n=>n.NetId.ToList();
var IgnoredList=r.Nets.Where(n=>n.NetStatus.Equals(“忽略”)).OrderBy(n=>n.NetId.ToList();
如果(newList.Count>0)
{
分拣报告。添加(r);
}
如果(upatedList.Count>0),则为else
{
分拣报告。添加(r);
}
其他的
{
分拣报告。添加(r);
}
}
创建一个列表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);
Li
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)
});
});