Linq GroupBy包含空键

时间:2013-11-24 15:49:57

标签: c# sql linq

我有一些层次结构的元素。我想要分组这些元素。

cuttingTools = machines.SelectMany(x0 => x0.Operations)
                       .SelectMany(x1 => x1.Tools)
                       .SelectMany(x2 => x2.CuttingTools)
                       .GroupBy(x => x.Tool.Operation.Machine) as IQueryable<IGrouping<T, CuttingTool>>;

但我有一个大问题。如果机器没有任何子操作,工具或切割工具,则结果不包含空组。例如:

Machine Tool
M1  T1
M1  T2
M1  T3
M2  T1
M2  T2
M3  Null

M1 [T1, T2, T3]
M2 [T1, T2]
M3 [None]   

但目前,M3不会出现在结果中。即使没有元素,我怎么能包括M3。

1 个答案:

答案 0 :(得分:1)

我相信您需要为空元素创建一些空的占位符值。 DefaultIfEmpty可以做到这一点。请注意,在下面的示例中,我直接由父机器分组,而无需访问工具内部属性(在您的情况下为x.Tool.Operation.Machine)。如果在您的方案中无法做到这一点 - 您需要以某种方式动态创建和初始化默认值,并引用父级。

using System;
using System.Linq;

class Machine
{
  public string MachineName;
  public Operation[] Operations;
}

class Operation
{
  public string OperationName;
  public Tool[] Tools;
}

class Tool
{
  public string ToolName;
  public Tool(string name) { ToolName = name; }
}

class App
{
  static void Main()
  {
    var machines = new[] 
    {
      new Machine {
        MachineName = "A", Operations = new[] { new Operation { OperationName = "O1", Tools = new[] { new Tool("T1") } } }
      },
      new Machine {
        MachineName = "B", Operations = new[] { new Operation { OperationName = "O3", Tools = new Tool[0] } }
      },
      new Machine {
        MachineName = "C", Operations = new Operation[0]
      }
    };

    var defaultOp = new Operation() { Tools = new Tool[0] };
    var defaultTool = new Tool("");

    var res = 
    from m in machines
    from o in m.Operations.DefaultIfEmpty(defaultOp)
    from t in o.Tools.DefaultIfEmpty(defaultTool)
    group t by m.MachineName;

    foreach(var g in res)
    {
      Console.WriteLine(g.Key + "=" + string.Join(";", g.Select(x => x.ToolName)));
    }
  }
}

输出:

A=T1
B=
C=