2016-12-06 121 views
0

我有一种方法,它使用大量LINQ来设置和匹配Tuple<string, int>列表中的某些值。Linq将两个语句合并为一个大语句(优化)

现在我仍然坚持嵌套到eachother中的两个foreach循环,我认为它可以将它们组合成一个巨大的LINQ查询。我想知道如何将优化作为一个大的条件来做到这一点,最好的办法是什么。

这是我讲的功能:

private async void AddLocalChangesFromPendingOperations() 
{ 
    var pendingOperations = await this.operationsStorage.GetOperationsAsync(); 
    var list = pendingOperations. 
     SelectMany(pendingOperation => 
          pendingOperation.Settings, (pendingOperation, setting) => 
          new { pendingOperation, setting }) 
     .Where(a => a.setting.Key == "selection") 
     .Select(a => new Tuple<string, int>(
              a.pendingOperation.DefinitionId, 
              Convert.ToInt32(a.setting.Value.ValueObject))) 
     .ToList(); 

    foreach (var pendingChange in list) 
    { 
     var selection = await this.selectionsStorage.GetSelectionByIdAsync(pendingChange.Item2); 
     foreach (var selectionsViewModel in this.SelectionsList.Where(a => a.Name == selection.Name)) 
     { 
      if (pendingChange.Item1 == "selection-add-animals") 
      { 
       selectionsViewModel.IsActive = true; 
      } 
      else if (pendingChange.Item1 == "selection-remove-animals") 
      { 
       selectionsViewModel.IsActive = false; 
      } 
     } 
    } 
} 

如果可能的话,我想同时使用LINQ优化最后两个foreaches。我试过的东西,但我被困在当前列表的设置值...

我这样做:

this.SelectionsList = this 
    .SelectionsList 
    .Where(a => a.Name == selection.Name) 
    .SingleOrDefault(
     a => pendingChange.Item1 == "selection-add-animals" ? a.IsActive = true : a.IsActive = false 
    ); 
+0

难道你不能只是改变方法GetSelectionByIdAsync接受ID列表,所以你摆脱了第一个foreach? –

回答

1

在一般来说,LINQ用于查询项目(Language Integrated Query)。然而,你可以做一个查询,然后在最后做一个foreach:

private async void AddLocalChangesFromPendingOperations() 
{ 
    var pendingOperations = await this.operationsStorage.GetOperationsAsync(); 

    (await Task.WhenAll(pendingOperations 
     .SelectMany(pendingOperation => 
          pendingOperation.Settings, (pendingOperation, setting) => 
          new { pendingOperation, setting }) 
     .Where(a => a.setting.Key == "selection") 
     .Select(a => Tuple.Create(a.pendingOperation.DefinitionId, Convert.ToInt32(a.setting.Value.ValueObject))) 
     .Select(async pendingChange => Tuple.Create(await this.selectionsStorage.GetSelectionByIdAsync(pendingChange.Item2)), pendingChange)) 
     .SelectMany(tuple => this.SelectionsList.Where(a => a.Name == tuple.Item1.Name) 
               .Select(selectionsViewModel => Tuple.Create(selectionsViewModel, tuple.Item2)) 
     .Select(tuple => Tuple.Create(tuple.Item1, tuple.Item2.Item1 == "selection-add-animals")) 
     .ToList() 
     .ForEach(tuple => tuple.Item1.IsActive = tuple.Item2); 
} 

这是否是更清晰的比你原来的实施问题讨论(我不认为这是),但它是一种方法做到这一点。

注意:这是直接键入编辑器,可能会有一些小的语法错误。

1

你可以这样做:

this.SelectionsList = this.SelectionsList 
    .Where(a => a.Name == selection.Name) 
    .Select(a => 
    { 
     a.IsActive = a.Name == selection.Name ? true:false; 
     return a; 
    }).ToList(); 
+1

由于LINQ延迟执行,您知道这不会执行任何操作。 –

+1

是的,抱歉,您应该使用ToList()执行查询。 – Johnny