C# 如何在嵌套表字段上使用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 =>

我有一份报告清单,每份报告都有一些“网络”。每个“网络”都有一个状态,我想根据它们可能具有的状态对这些报告重新排序。我写的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的类型”,这很有道理。我无法理解的是,如何正确地传达我在第一段中所说的订购内容。

我想您可能误解了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)
               });
    });