linq中的可选随机有序嵌套分组

时间:2016-07-15 19:15:08

标签: c# linq

我真的处于一个我无法想到关于linq中可选分组的答案的位置。

基本上,我想生成来自具有过滤器的屏幕的报告。 这些过滤器(大多数是分组的)是可选的,可以重新排列。它类似于

Filters: 1.Clients Projects Tasks Duration
                or 
         2.Projects Clients  Tasks Duration
                or 
         3.Task Duration etc.

所有可能的组合。 那么数据应该看起来像

1.ClientA
     ProjectA
        TaskA
             26hrs 45mins
        TaskB
             43hrs 23mins
    ProjectB
      TaskX......
2.ProjectA
    ClientA
       TaskA
             26hrs 45mins...

3.TaskA
      26hrs 45mins
  TaskB
     6hrs 35mins

我有数据。但是无法编写通用的逻辑。

我正在考虑使用一些enum来保持选择的过滤器(viewmodel)    enum.Client,enum.Project ...和

 if (clientGroupChecked) then 
     foreach(var clientGroup in list){
        //group list by client here
     if(projectGroupChecked) then
        foreach(var projectGroup in clientGroup){
        //group list by project here
}
}

我知道,这是错误的。这样我就必须为所有可能的组合设置逻辑
无法想到其他任何事情。我希望它真的被推广因为它可能会在未来添加更多过滤器而我不想仅为额外过滤器更改整个逻辑(当然,我想在逻辑中的某处添加新的过滤器组。但是我希望它也更容易维护。

已编辑:
@sschimmel :我的观点是分组可以改组(为此我有按钮[已选择 - >绿色和未选中 - >灰色和这些按钮可以移动进行分组]。
因此,当编写linq逻辑时,我怎么知道我必须以特定的方式分组的标准?
对于ex:我有列ABCDE F.在此,我可以选择按A或AB或BA或ACB等分组。所有可能的组合。如何实现这一目标?我不想要其他检查,因为我们有很多可能性。如果添加了一个更多过滤器,它会有很多更多可能性。这就是为什么我我正在考虑需要一般方法来做到这一点。

编辑2

请查找附件以及我在下面尝试的方式。

    //for the following ,I need some way of writing properly passing right values
    var reportGroupingCP = (from t in TaskEntries
                          group t by new { clientId,projectId  } into g
                          select new 
                          {
                              ClientId = g.Key.clientId,
                              ProjectId = g.Key.projectId,
                             Result = (Type)g //What could be T
                          }).ToList();



   var reportGroupingCE = (from t in  TaskEntries
                          group t by new { clientId,employeeId } into g
                          select new 
                          {
                              ClientId = g.Key.clientId,
                              EmployeeId = g.Key.employeeId,
                              Result = (Type)g //What could be T
                          }).ToList();
    //Can't use above if there is filter only for client.similarly for other cases/I don't want to write for each one.I need way to do this dynamically.May be by passing enum or adding ids to some class or something else

Filter 1

Filter 2

1 个答案:

答案 0 :(得分:0)

如果我理解你的问题,你就不要在多个属性上动态地对数据进行分组。

最简单的解决方案是使用Dynamic LINQ,它可以让您根据用户输入轻松编写的字符串创建查询。

// userSelections is created dynamically from what the user selected.
var userSelections = new[] { "clientId", "projectId" };
var propertiesToGroupBy = string.Join(", ", userSelections);
var groupedData  = data.GroupBy("new(" + propertiesToGroupBy + ")");

它不是类型安全的,也不是在编译期间检查过,但是相当容易使用并解决了你的问题。它也是documented nicely

我尝试提出一个动态组合Expression<Func<TaskEntry, object>>的解决方案,但却坚持创建Expression,以便在GroupBy(new { ... })内实现您将使用的匿名类型。由于在编译期间不知道要分组的所选属性的数量,因此无法创建匿名类型。